echo znak nowej linii nie działa w bash

13

Mam skrypt bash, który ma wiele echoinstrukcji, a także alias echodo echo -eobu w .bash_profilei .bashrc, dzięki czemu nowe wiersze są drukowane poprawnie dla instrukcji takich jak echo 'Hello\nWorld'wynik powinien być

Hello
World

ale otrzymuję wynik

Hello\nWorld

Próbowałem nawet użyć shopt -s expand_aliasesw skrypcie, to nie pomaga

Uruchamiam skrypt jako bash /scripts/scriptnm.sh; jeśli uruchomię go, gdy . /scripts/scriptnm.shotrzymuję pożądaną wydajność ...

Bashuser
źródło
3
aliasing, echojak chcesz, to zła praktyka IMHO
shellholic
1
Użyj podwójnych cudzysłowów, aby \ n został zinterpretowany. Pojedyncze cudzysłowy uniemożliwiają interpretację \ n i wielu innych rzeczy.
BillThor,

Odpowiedzi:

16

Mieszana historia echooznacza, że ​​jej domyślne działanie różni się w zależności od powłoki. POSIX określa, że wynikiem echojest „zdefiniowany w implementacji”, jeśli pierwszym argumentem jest -nlub dowolny argument zawiera odwrotny ukośnik.

Bardziej niezawodne jest użycie printf(jako polecenia wbudowanego lub polecenia zewnętrznego), gdzie zachowanie jest lepiej zdefiniowane: znaki odwrotnego ukośnika w stylu C i specyfikatory formatu są obsługiwane w ciągu formatu (pierwszy argument).

printf 'foo\nbar\n'
printf '%s\n%s\n' foo bar

Można kontrolować ekspansję BACKSLASH sekwencje z bash „s echowbudowane polecenie z xpg_echoopcją powłoki.

Ustaw go u góry dowolnego skryptu bash, aby echoautomatycznie rozszerzać sekwencje specjalne odwrotnego ukośnika bez konieczności dodawania -edo każdego polecenia echa.

shopt -s xpg_echo
echo 'foo\nbar'
Chris Johnsen
źródło
shopt -s xpg_echo; Pracował dla mnie.
Bashuser
6

Gdy używasz bash myfile.sh, Bash jest uruchamiany w trybie „wsadowym”, w osobnym procesie i nie odczytuje swojego profilu ani pliku rc.

Kiedy używasz . myfile.sh, plik jest pobierany przez bieżący proces powłoki (tak jakby jego zawartość została przez Ciebie wpisana), dlatego widzi twoje aktualnie zdefiniowane aliasy.

Zasadniczo pisanie skryptów zależnych od konkretnej konfiguracji powłoki, zwłaszcza aliasów, jest bardzo złym pomysłem , chyba że zdefiniujesz je w samym skrypcie . ( Nigdy nie polegaj na użytkowniku .bashrc, nawet jeśli jest on Twój).

użytkownik1686
źródło
5

Zalecaną praktyką jest stosowanie printfwszystkich nowych skryptów.

printf '%s\n%s\n' "Hello" "World"

printf '%s\n' "Hello\nWorld"
Wstrzymano do odwołania.
źródło
+1 printf jest nieco bardziej skomplikowany w użyciu niż echo, ale bardziej niż opłaca się unikać niespójności echa.
Gordon Davisson,
1

Działa to dobrze w terminalu

#!/bin/bash
alias echo="echo -e"
echo "Hello\nWorld"

zapisz do pliku i uczyń go wykonalnym (chmod + x)

uruchom jako ./twoj_plik

LaLeX
źródło
uruchom go jako bash twój_plik i sprawdź dane wyjściowe.
Bashuser,
Działa zgodnie z oczekiwaniami
LaLeX
ale echo „Hello \ nWorld” nie wyświetla oczekiwanego wyniku. Ponieważ echo jest już aliasowane do echa -e powinno, ale to nie działa i to jest moje pytanie
Bashuser
Ponieważ złą praktyką jest używanie echa aliasu (programy, które od niego zależą mogą się zepsuć), powinieneś usunąć alias iw swoim skrypcie szukać końca echa zastąpić go echo -e
LaLeX 11.11
Wielkie dzięki LaLex za twoje odpowiedzi, czy jest sposób, w jaki mogę osiągnąć oczekiwany wynik z aliasem, chociaż nie jest to dobra praktyka
Bashuser