2012-05-14 7 views
12

Chciałbym użyć echo w bash, aby wydrukować ciąg znaków, po którym następuje tylko powrót karetki. Przejrzałem stronę podręcznika i stwierdziłem, że echo -e spowoduje interpretację znaków ułamkowych odwrotnych ukośników. Korzystanie że mogę powiedzieć echo -e 'hello\r' i będzie drukować takJak interpretować echo odwrotne ukośniki odwrotne, a nie drukować końcowy znak nowej linii?

$>echo -e 'hello\r' 
hello 
$> 

Wygląda więc na to, że zajmował się powrotu karetki prawidłowo. Znalazłem również echo -n w manualu zatrzyma echo z wstawiając znak nowej linii i wygląda na to, że działa, kiedy to zrobić

$>echo -n 'hello\r' 
hello\r$> 

Problem Mam to w połączeniu zarówno -e i -n. Próbowałem każdej echo -e -n 'hello\r', echo -n -e 'hello\r', echo -en 'hello\r' i echo -ne 'hello\r' i nic nie zostanie wydrukowany tak:

$>echo -ne 'hello\r' 
$> 

Czy coś mi tu brakuje lub może opcje -e i -n nie mogą być używane razem?

+0

'$> echo -ne 'hello \ r'' spowoduje opuszczenie kursora na początku wiersza zawierającego' hello '. Więc jeśli twój monit jest dłuższy niż '$>', który masz tutaj, to nadpisze powitanie. –

+0

"nic nie zostanie wydrukowane"? Z pewnością dostaniesz '' $> llo', ponieważ twój 2-znakowy tekst zachęty nie całkowicie zastąpi 5 znaków "cześć". Zwróć uwagę, że "powrót karetki" nie jest tym samym, co "nowa linia" (patrz "man ascii"). Wygląda więc na to, że udało ci się zastąpić nową linię zwrotem karetki, ale jesteś zaskoczony, że powrót karetki nie zachowuje się jak nowa linia. Dlaczego chcesz to zrobić? Jestem ciekawy. Również bez cudzysłowów powłoka interpretuje ukośnik odwrotny jako znak ucieczki, więc '\ r' po prostu staje się' r'. Oznacza to, że twoje pierwsze polecenie wypisuje "hellor", a nie "' cześć ". –

+0

Czy uruchomiłeś te polecenia w tej samej powłoce? 'echo -n hello \ r' powinno wypisać dokładnie to samo, co' echo -ne hello \ r'; obaj drukują "hellor" (bez nowej linii, więc pytanie pojawia się jako "hellor $>"). "-e" nie ma tutaj znaczenia, ponieważ po usunięciu powłoki nie ma ucieczki wstecz. 'echo -ne 'hello \ r'' lub' echo -ne hello \\ r' oba przekazują argument' 'hello \ r' 'do' echo'. –

Odpowiedz

14

Myślę, że to działa, po prostu go nie widzisz. To jest Twój polecenia:

$> echo -ne 'hello\r' 

powodu powrotu karetki (\r), która pozostawi kursor na początku tej samej linii na terminalu, gdzie napisał hello - co oznacza, że ​​tam następnego wyjścia rzeczą do terminala zostaną zapisane. Więc jeśli aktualny monit jest dłuższy niż pokazany tutaj $>, całkowicie zastąpi on kod hello.

Sekwencja ta pozwoli Ci zobaczyć, co się rzeczywiście dzieje:

echo -ne 'hello\r'; sleep 5; echo 'good-bye' 

Ale dla lepszego przenoszenia do innych skorup, chciałbym uniknąć używając opcji na echo takiego. Są to czysto bashisms, nie obsługiwane przez standard POSIX. Jednak wbudowany printf jest określony przez POSIX. Więc jeśli chcesz wyświetlić struny bez nowej linii i analizowania sekwencji backslash, można po prostu użyć go:

printf '%s\r' 'hello' 
+0

Tak, to było to. Dzięki – seanwatson

1

Cytowanie. To fala przyszłości. Zawsze cytuj.

echo -ne 'hello\r' 

Użyj podwójnych cudzysłowów, jeśli wstawisz do wnętrza zmienną, którą chcesz rozwinąć.

+0

Cytowanie też nie działa. Kiedy używam cytatów, nic nie zostanie wydrukowane. Zaktualizuję pytanie dla tego – seanwatson

+0

@ swatso33: To działa dla mnie. Co otrzymasz, gdy spróbujesz: 'echo" $ BASH_VERSION "' –

+0

Jego wersja '4.2.24 (2) -release'. Działa na arch. Linux, jeśli robi różnicę. Musi to być po prostu moja wersja. W której wersji pracujesz? – seanwatson

10

Istnieje wiele różnych implementacje komendy echo. Jest jeden wbudowany w większość powłok (z różnymi zachowaniami dla każdego), a zachowanie /bin/echo różni się znacznie w zależności od systemu.

Zamiast echo użyj printf. Jest wbudowany w bash, a także dostępny jako zewnętrzne polecenie, a jego zachowanie jest znacznie bardziej spójne we wszystkich implementacjach. (Główną odmianą jest to, że GNU coreutils printf rozpoznaje opcje --help i .)

Wystarczy użyć:

printf 'hello\r' 
+2

+1 "echo" nadaje się do drukowania pojedynczych linii, ale gdy tylko użyjesz specjalnych opcji lub ucieczek, staje się niewiarygodny i nieprzewidywalny. 'printf' jest znacznie lepszy dla czegoś takiego. –

+0

Pytanie jest jednak oznaczone jako bash-specific. Wydaje się prawdopodobne, że OP nie wymaga przenośności w ich przypadku użycia. –

6

Chciałbym Ci przedstawić Wam printf.

OP, poznaj printf. printf. To jest OP ...

Ilekroć próbujesz zrobić cokolwiek nietypowy z wyjściem w BASH, powinieneś przełączyć na printf. W rzeczywistości cały czas używam printf, więc moje skrypty będą działać zarówno pod BASH, jak i Kornshell.

Mimo że BASH i Kornshell są w 99% identyczne, polecenie echo jest inne. W Kornshell jest to przestarzałe i powinieneś używać wbudowanego print. Jednak w BASH nie ma wartości print. Używanie printf rozwiązuje problem, ponieważ działa (sortuje) tak samo w obu powłokach.

Ponieważ printf nie kończy automatycznie każdej linii z \n, nie musisz się martwić, jak zapobiec dołączeniu \n. Heck, jeśli chcesz \n, musisz to zrobić sam. W twoim przypadku:

printf `hello\r` 

Jednakże, ze względów bezpieczeństwa, należy naprawdę to zrobić:

printf '%s\r' 'hello' 

Jest to nawyk stałam się gdy używam printf. Wyobraź sobie, że chcę wydrukować $FOO i zrobić to:

printf "$FOO\n" 

To będzie pracować normalnie, ale co jeśli $FOO ma kreskę na początku lub ma % znak w nim. Powyższe nie zrobi tego, co chcę zrobić. Jednakże, jeśli mogę to zrobić:

printf '%s\n' "$FOO" 

To będzie wydrukować $FOO nieważne co $FOO ma w nim.

+0

FYI, twój pierwszy przykład 'printf' ma cofnięcia zamiast apostrofów. –

1

POSIX 7 says it is not possible:

Jeśli pierwszy argument jest -n, lub jeśli któryś z argumentów zawiera ukośników, wyniki są zdefiniowane w implementacji.

Na Ubuntu 12.04 na przykład:

  • Bash wbudowanej echo echo -e '\n' interpretuje przełamane, echo '\n' nie.
  • /bin/sh 's wbudowany echo nie ma opcji -e i interpretuje znak nowego wiersza nawet bez niego. Może to być bajt podczas pisania Makefile s, które domyślnie używają /bin/sh.

Rozwiązanie POSIX 7: printf, jak wspomnieliśmy o innych.

+0

To POSIX; OP zapytał konkretnie o bash. A zachowanie 'echo' * w bashie * jest dobrze zdefiniowane i udokumentowane, włączając opcje' -e' i '-n' oraz traktowanie odwróconych ukośników. –

+0

@ Mark Reed Nigdy nie twierdziłem, że jest inaczej. Ale wielu pracowników Google, którzy tu przyjeżdżają, może być również zainteresowanych zachowaniem POSIX-a. –

Powiązane problemy