Jeśli mam ciąg znaków z niedrukowalnymi znakami, nowymi wierszami lub tabulatorami, czy istnieje sposób echona wydrukowanie tego ciągu i pokazanie kodów dla tych znaków (np. \nDla nowego wiersza, \bdla backspace)?
printf '%q' "$str"wypisze znak ucieczki. Nie dodam tego jako odpowiedzi, ponieważ nie jest to ta sama forma ucieczki, która echo -eużywa - raczej ma być bezpieczna dla ewaluacji - ale (1) jest wystarczająco dobra, jeśli twoim celem jest czytelność dla ludzi, (2) to wystarczająco dobre, jeśli twoim celem jest bezpieczne generowanie powłoki, a (3) echo -ejest złe i złe w każdym razie (jeśli przeczytasz specyfikację POSIX, zobaczysz, że printf jest preferowanym sposobem formatowania łańcucha i echo -enie jest gwarantowane przez bazowe POSIX na wszystko).
Charles Duffy,
Odpowiedzi:
7
Można to zrobić na wiele sposobów. Najbardziej przenośne dwa, jakie znam, to sedi od- oba są POSIX.
printf '\n\r\b\t\033[01;31m'| sed -n l
To lubi ... readucieczki stylu - styl C.
WYNIK
$
\r\b\t\033[01;31m$
od jest trochę bardziej konfigurowalny ...
printf '\n\r\b\t\033[01;31m'|
od -v -w12 -t c -t a -A n
\n \r \b \t 033[01;31 m
nl cr bs ht esc [01;31 m
Jeśli chcesz wiedzieć, w jakie te wszystkie opcje możesz zajrzeć man od, ale określam, że chcę dwóch rodzajów znaków ucieczki - znaków -t codwrotnego ukośnika i -t anazwanych postaci. -wOpcja nie jest używane powyżej POSIX określony.
A oto mała funkcja powłoki, która w przenośny sposób wypisuje wartości ósemkowe każdego bajtu w swoich argumentach - które oczywiście odmogłyby również obsługiwać -t o:
proctal()(LC_ALL=C
for a dowhile[-n "$a"]do printf %o\\n "'$a"
a=${a#?}; done; done)
To jest proste. To jest trochę bardziej skomplikowane. Powinno być w stanie robić to, co printf -qmogą implementacje specyficzne dla powłoki .
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/$$//')
Wykorzystując przykładowy ciąg z wcześniejszego z odrobiną dodatkowej:
bsq "$(printf '\n\r\'\''b\t\033[01;31m')"
WYNIK
'\n\r\\'\''b\t\0033[01;31m'
Jest tylko nieco inny. Możesz zauważyć, że istnieje dodatkowy 0i dodatkowy \backslash. Ma to na celu umożliwienie łatwego tłumaczenia na argument readlub %bprintfargument. Na przykład:
i=0until[ $((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
@ StéphaneChazelas Nadal będzie robił tylko znaki jednobajtowe, ale mam nadzieję, że teraz jest mniej prawdopodobne, że się zepsuje.
mikeserv
1
Pozwól, że zabiorę Cię do 10 000 :)
Ramesh
Woohoo !!!!!!!!!
slm
@slm - niech zgadnę .. Naprawdę podobało ci się proctal?
mikeserv
@ StéphaneChazelas - czy masz jakieś przemyślenia na temat bsq()- czy czegoś brakuje? Pytam, ponieważ nie jestem całkowicie pewny co do odwrotnych ukośników.
mikeserv
12
Po usunięciu -eprzełącznika na echo, w bashi pod warunkiem, że xpg_echoopcja nie została włączona, łańcuchy powinny być drukowane jako nic więcej niż oryginalny tekst. Tak \ni \tpokazałby się dosłownie tak.
Przykład
$ echo "hi\t\tbye\n\n"
hi\t\tbye\n\n
$ echo -e "hi\t\tbye\n\n"
hi bye
Można również skorzystać z printfwbudowanego w dowodzenie ksh93, zshalbo bashfinagle to za dobrze.
Nie chodzi o to, printf %qże obcinają końcowe \ns, lecz $()przechwytywanie danych wyjściowych, które je rozbiera.
ecatmur
@ ecatmur - dzięki, że napisałem to późno w nocy i nie próbowałem dalej debugować. Miałbyś rację, to ta podpowłoka usuwa je. Oto powód, dla którego: unix.stackexchange.com/questions/17747/…
slm
... w każdym razie uruchamianie printfwewnątrz podpowłoki w celu przechwytywania danych wyjściowych jest głupie, ponieważ printf -v varnameumieści dane wyjściowe bezpośrednio w zmiennej, bez udziału podpowłoki.
Charles Duffy,
@CharlesDuffy - Nie podążam za tobą, nie działam printfw podpowłoce, działałem echow jednym, tylko po to, aby pokazać, że możesz pobrać dane wyjściowe ze znaków specjalnych echoi przekonwertować je z powrotem na notację ucieczkową.
slm
@slm, to była odpowiedź na pierwszy komentarz (no cóż, kod, na który odpowiedział pierwszy komentarz), a nie kod taki, jaki go teraz znalazłem. Jeśli wywnioskowałem coś niedokładnego na temat stanu poprzedniej edycji, przepraszam.
e- ohce
* rimshot *printf '%q' "$str"
wypisze znak ucieczki. Nie dodam tego jako odpowiedzi, ponieważ nie jest to ta sama forma ucieczki, któraecho -e
używa - raczej ma być bezpieczna dla ewaluacji - ale (1) jest wystarczająco dobra, jeśli twoim celem jest czytelność dla ludzi, (2) to wystarczająco dobre, jeśli twoim celem jest bezpieczne generowanie powłoki, a (3)echo -e
jest złe i złe w każdym razie (jeśli przeczytasz specyfikację POSIX, zobaczysz, że printf jest preferowanym sposobem formatowania łańcucha iecho -e
nie jest gwarantowane przez bazowe POSIX na wszystko).Odpowiedzi:
Można to zrobić na wiele sposobów. Najbardziej przenośne dwa, jakie znam, to
sed
iod
- oba są POSIX.To lubi ...
read
ucieczki stylu - styl C.WYNIK
od
jest trochę bardziej konfigurowalny ...Jeśli chcesz wiedzieć, w jakie te wszystkie opcje możesz zajrzeć
man od
, ale określam, że chcę dwóch rodzajów znaków ucieczki - znaków-t c
odwrotnego ukośnika i-t a
nazwanych postaci.-w
Opcja nie jest używane powyżej POSIX określony.A oto mała funkcja powłoki, która w przenośny sposób wypisuje wartości ósemkowe każdego bajtu w swoich argumentach - które oczywiście
od
mogłyby również obsługiwać-t o
:To jest proste. To jest trochę bardziej skomplikowane. Powinno być w stanie robić to, co
printf -q
mogą implementacje specyficzne dla powłoki .Wykorzystując przykładowy ciąg z wcześniejszego z odrobiną dodatkowej:
WYNIK
Jest tylko nieco inny. Możesz zauważyć, że istnieje dodatkowy
0
i dodatkowy\b
ackslash. Ma to na celu umożliwienie łatwego tłumaczenia na argumentread
lub%b
printf
argument. Na przykład:WYNIK
źródło
proctal
?bsq()
- czy czegoś brakuje? Pytam, ponieważ nie jestem całkowicie pewny co do odwrotnych ukośników.Po usunięciu
-e
przełącznika naecho
, wbash
i pod warunkiem, żexpg_echo
opcja nie została włączona, łańcuchy powinny być drukowane jako nic więcej niż oryginalny tekst. Tak\n
i\t
pokazałby się dosłownie tak.Przykład
Można również skorzystać z
printf
wbudowanego w dowodzenieksh93
,zsh
albobash
finagle to za dobrze.(
fragmentbash
dane wyjściowe pokazano powyżej. Istnieje kilka odmian w zależności od powłoki).help printf
wbash
źródło
printf %q
że obcinają końcowe\n
s, lecz$()
przechwytywanie danych wyjściowych, które je rozbiera.printf
wewnątrz podpowłoki w celu przechwytywania danych wyjściowych jest głupie, ponieważprintf -v varname
umieści dane wyjściowe bezpośrednio w zmiennej, bez udziału podpowłoki.printf
w podpowłoce, działałemecho
w jednym, tylko po to, aby pokazać, że możesz pobrać dane wyjściowe ze znaków specjalnychecho
i przekonwertować je z powrotem na notację ucieczkową.Możesz użyć czegoś takiego,
Teraz możesz zrobić coś takiego,
Wynik
Kolejnym ogólnym testem bez plików jest:
Powyższe polecenie zwraca dane wyjściowe jako,
Bibliografia
źródło
Dzięki
zsh
, tam są(q)
,(qq)
,(qqq)
,(qqqq)
zmienne flagi rozszerzeń, które mogą cytowanie zmiennych na różne sposoby:W twoim przypadku prawdopodobnie chcesz jednego z dwóch ostatnich.
źródło
od -c
wypisze normalne znaki normalnie, ale znaki specjalne (tab, znak nowej linii itp.) i znaki niedrukowalne jakoprintf
kod ucieczki.Więc:
-An
Mówiod
nie wyjście adres.źródło
Użyj
printf
polecenia. Na przykład:printf "Hello\nthis is my line
wyjdzie
źródło
echo -e
szukam na odwrocie .