Что обратного эхо-е?

13

Если у меня есть строка с непечатаемыми символами, новыми строками или вкладками, есть ли способ использовать echoэту строку для печати этой строки и отображения кодов для этих символов (например, \nдля новой строки, \bдля возврата на одну позицию )?

DRS
источник
2
вы можете использовать команду printf, см. man printf
PersianGulf
12
e- ohce* rimshot *
Дэвид Ричерби,
3
printf '%q' "$str"напечатает экранированную строку Я не добавляю это как ответ, так как это не та же самая форма побега, которая echo -eиспользует - скорее, она предназначена для безопасности eval - но (1) это достаточно хорошо, если ваша цель - читабельность человеком, (2) это достаточно хорошо, если ваша цель - безопасное создание оболочки, и (3) в echo -eлюбом случае это зло и зло (если вы прочитаете спецификацию POSIX, вы увидите, что printf является предпочтительным способом форматирования строк и echo -eне гарантируется базовой версией POSIX при все).
Чарльз Даффи

Ответы:

7

Есть много способов сделать это. Самые переносимые два из известных мне - sedи odоба - POSIX.

printf '\n\r\b\t\033[01;31m' | sed -n l

Это как ... readстиль избегает - С-стиль.

ВЫХОД

$
\r\b\t\033[01;31m$

od немного более настраиваемый ...

printf '\n\r\b\t\033[01;31m' |
od -v -w12 -t c -t a -A n

 \n  \r  \b  \t 033   [   0   1   ;   3   1   m
 nl  cr  bs  ht esc   [   0   1   ;   3   1   m

Если вы хотите знать, что вы можете посмотреть во всех этих опциях man od, но я уточняю, что я хочу два типа экранирования - экранирование с -t cобратной косой чертой и -t aименованные символы. -wПараметр , используемый выше, не является POSIX-указания.

А вот небольшая функция оболочки, которая будет выводить восьмеричные значения каждого байта в своих аргументах, что, конечно же, odможет работать и с -t o:

proctal() (LC_ALL=C
    for a do while [ -n "$a" ] 
    do printf %o\\n "'$a"
    a=${a#?}; done; done)  

Это простой. Это немного сложнее. Он должен быть в состоянии делать то, что могут делать специфичные для оболочки printf -qреализации.

bsq() (set -f; export LC_ALL=C IFS=\'
    for a do q=${a##*\'}; printf \'
    [ -n "${a#"$q"}" ] &&
        printf "%s'\''" ${a%\'*}
    printf "%s'\n'''''\n" "$q"; done |
    sed -n "/'''''"'/!H;1h;//!d;$!n;x;l' |
    sed -e :n -e '/\\$/N;s/.\n//;tn
        s/\([^\\]\\\(\\\\\)*\)\([0-9]\)/\10\3/g
        s/\\\\'"''/\\\\''"'/g;s/$$//'
)

Используя пример строки из ранее с небольшим дополнительным:

bsq "$(printf '\n\r\'\''b\t\033[01;31m')"

ВЫХОД

'\n\r\\'\''b\t\0033[01;31m'

Это только немного отличается. Вы можете заметить, что есть дополнительный 0и дополнительный \bудар. Это позволяет легко переводить аргументы readили %b printfаргументы. Например:

i=0
until [ $((i=$i+1)) -gt 5 ]
do touch "\%$i$(printf 'hey\b \t;\n\033 ')"
done   #just for ugly's sake

bsq * | eval "
    printf '<%b>\n' $(tr \\n \ )
" | tee /dev/fd/2 |
sed -n l

ВЫХОД

<\%1he  ;
>
<\%2he  ;
>
<\%3he  ;
>
<\%4he  ;
>
<\%5he  ;
>
<\\%1hey\b \t;$
\033 >$
<\\%2hey\b \t;$
\033 >$
<\\%3hey\b \t;$
\033 >$
<\\%4hey\b \t;$
\033 >$
<\\%5hey\b \t;$
\033 >$
mikeserv
источник
@ StéphaneChazelas Он по- прежнему будет выполнять только однобайтовые символы, но, надеюсь, сейчас он вряд ли испортится.
Mikeserv
1
Позвольте мне довести вас до отметки 10k :)
Ramesh
Woohoo !!!!!!!!!
СЛМ
@slm - дай угадаю .. Тебе действительно понравилось proctal?
mikeserv
@ StéphaneChazelas - есть ли у вас какие-либо мысли о bsq()том, что-то не хватает? Я спрашиваю, потому что я не совсем уверен насчет обратной косой черты.
mikeserv
12

Когда вы убираете -eпереключатель в echo, в bashи при условии, что xpg_echoопция не была включена, он должен печатать строки как не более чем их исходный текст. Так \nи \tпоявилось бы буквально так.

пример

$ echo "hi\t\tbye\n\n"
hi\t\tbye\n\n

$ echo -e "hi\t\tbye\n\n"
hi      bye

Вы также можете использовать printfвстроенную команду ksh93, zshили, bashчтобы найти это тоже.

$ printf "%q\n" "$(echo -e "hi\t\tbye\n\nbye")"
$'hi\t\tbye\n\nbye'

( bashвывод показан выше. Существуют некоторые вариации в зависимости от оболочки).

выдержка изhelp printf вbash

%q цитируйте аргумент таким образом, чтобы его можно было повторно использовать в качестве входных данных оболочки

SLM
источник
1
Дело не в printf %qтом, что они усекают концевые \ns, а в $()выводе, который их убирает.
Ecatmur
@ecatmur - спасибо, я написал это поздно ночью и не пытался отлаживать дальше. Вы были бы правы, это та скорлупа, которая их срывает. Вот причина , почему: unix.stackexchange.com/questions/17747/...
ОДС
... как бы то ни было, printfглупо работать внутри подоболочки для захвата ее вывода, так printf -v varnameкак вывод будет помещен непосредственно в переменную, не задействуя подоболочку.
Чарльз Даффи
@CharlesDuffy - я не слежу за тобой, я не работаю printfв подоболочке, я запустил echoодну, только для того, чтобы продемонстрировать, что ты можешь взять вывод специального символа echoи преобразовать его обратно в экранированную запись.
СЛМ
@slm, это был ответ на первый комментарий (ну, код, на который ответил первый комментарий), а не тот код, который я нашел сейчас. Если я предположил что-то неточное в предыдущем состоянии редактирования, мои извинения.
Чарльз Даффи
5

Вы могли бы использовать что-то вроде,

$ cat filename
Ramesh is testing
New Line        is

Теперь вы можете сделать что-то вроде,

$ cat -A filename

Выход

Ramesh is testing$
New Line ^Iis $

Еще одно общее тестирование без каких-либо файлов, как,

$ echo Hello$'\t'world. | cat -A

Приведенная выше команда выдает результат как

Hello^Iworld.$

Ссылки

Рамеш
источник
4
Или, в не-GNU реализация кошки, например , MacOS / X, возьмите свою кошку к ветеринару ... кошка -v
Tink
3

С zsh, Есть (q), (qq), (qqq), (qqqq)переменная флаги расширения , которые могут процитировать переменные различными способами:

$ a=$'a b\nba\bc\u00e9\0'

$ printf '%s\n' $a
a b
bcé

$ printf %s $a | od -vtc
0000000   a       b  \n   b   a  \b   c 303 251  \0
0000013

$ printf '%s\n' ${(q)a}
a\ b$'\n'ba$'\b'cé$'\0'

$ printf '%s\n' ${(qq)a}
'a b
bcé'

$ printf '%s\n' ${(qqq)a}
"a b
bcé"

$ printf '%s\n' ${(qqqq)a}
$'a b\nba\bcé\0'

$ (){local LC_ALL=C; print -r -- ${(qqqq)a}}
$'a b\nba\bc\303\251\0'

В вашем случае вы, вероятно, захотите один из двух последних.

Стефан Шазелас
источник
1

od -cбудет печатать обычные символы в обычном порядке, но специальные символы (табуляция, новая строка и т. д.) и непечатаемые символы в качестве printfкода перехода.

Так:

$ echo -e asdf\\nghjk\\003foo | od -c -An
   a   s   d   f  \n   g   h   j   k 003   f   o   o  \n

-AnГоворит odне выводится адрес.

Брайан Минтон
источник
-1

Используйте printfкоманду. Например:

printf "Hello\nthis is my line

будет выводить

Hello
this is my line
Лазуарди N Путра
источник
1
Это же , как echo -e, я смотрю на реверсе .
DRS
Можете ли вы привести конкретный пример?
Лазуарди N Путра