Jak dodać nowe linie podczas korzystania z echa


42

Dlaczego poniższe polecenie nie wstawia nowych wierszy do generowanego pliku i jakie jest rozwiązanie?

$ echo "Line 1\r\nLine2" >> readme.txt

$ cat readme.txt 
Line 1\r\nLine2

6
Jest echoobowiązkowe? możesz użyć printf.
Archemar

Nie wiedziałem o printf, z printf to działa: P ... więc co sprawia, że ​​nie działa z echo?
Saeid Yazdani

Czy \rzawiera w wyjściu lub jest częścią CRLFnowego wiersza?
cuonglm

9
Istnieje wiele różnych implementacji echopoleceń niezgodnych ze sobą. Dlatego zaleca się stosowanie bardziej standardowego narzędzia jako printf. Zobacz unix.stackexchange.com/questions/65803/…, aby uzyskać rozszerzony przegląd problemu.
jimmij

Odpowiedzi:


38

echo


echoRealizacja które ściśle zgodny z Single Unix Specification doda znaki nowej linii, jeśli zrobić:

echo 'line1\nline2'

Ale to nie jest wiarygodne zachowanie. W rzeczywistości nie ma żadnego standardowego zachowania, którego można by oczekiwać echo.

OPERACJE

string

Ciąg do zapisania na standardowe wyjście. Jeśli pierwszym operandem jest -nlub jeśli którykolwiek z operandów zawiera znak < \odwrotny ukośnik> , wyniki są zdefiniowane w implementacji .

W systemach zgodnych z XSI , jeśli pierwszym operandem jest -n, należy go traktować jako ciąg, a nie opcję . Następujące sekwencje znaków należy rozpoznać w systemach zgodnych z XSI w ramach jednego z argumentów:

\a- Napisz <alert> .

\b- Napisz <backspace> .

\c- Pomiń <nową linię >, która w przeciwnym razie następuje po ostatnim argumencie w danych wyjściowych. Wszystkie znaki następujące \cpo argumentach zostaną zignorowane.

\f- Napisz <feed-feed> .

\n- Napisz < nową linię > .

\r- Napisz <powrót karetki> .

\t- Napisz <tab> .

\v- Napisz <tabertę> .

\\- Wpisz znak <lashlash> .

\0num- Napisz 8-bitową wartość, która jest zerową, jedną, dwiema lub trzycyfrowymi liczbami ósemkowymi num.

Tak więc naprawdę nie ma żadnego ogólnego sposobu, aby wiedzieć, jak napisać nowy wiersz, z echowyjątkiem tego, że ogólnie możesz polegać tylko echona zrobieniu tego.

bashPowłoki zazwyczaj nie nie są zgodne ze specyfikacją i obsługuje -ni inne opcje, ale nawet to nie jest pewne. Możesz to zrobić:

shopt -s xpg_echo
echo hey\\nthere

hey
there

I nawet to nie jest konieczne, jeśli bashzostało zbudowane z opcją czasu kompilacji ...

--enable-xpg-echo-default

echoPowoduje, że wbudowane rozszerzenie domyślnie rozwija znaki specjalne z odwrotnym ukośnikiem, nie wymagając -eopcji. Powoduje to ustawienie domyślnej wartości xpg_echoopcji powłoki na on, dzięki czemu Bash echozachowuje się bardziej jak wersja określona w specyfikacji Single Unix, wersja 3. Zobacz Wbudowane wersje Bash , aby zapoznać się z opisem echorozpoznawalnych sekwencji ucieczki .


printf


Z drugiej strony printfzachowanie jest dość oswojone w porównaniu.

RACJONALNE UZASADNIENIE

printfNarzędzie dodano w celu zapewnienia funkcji, które w przeszłości były dostarczone przez echo. Jednak z powodu niemożliwych do pogodzenia różnic w różnych wersjach echoistniejących, wersja ma kilka specjalnych funkcji, pozostawiając je nowemu printfnarzędziu, które jest oparte na jednym w systemie Dziewiątej Edycji.

Sekcja ROZSZERZONY OPIS prawie dokładnie odpowiada printf()funkcji w standardzie ISO C, chociaż jest opisana w kategoriach zapisu formatu pliku w zapisie formatu pliku XBD .

Obsługuje ciągi formatujące, które opisują jego argumenty - może to być dowolna liczba rzeczy, ale dla ciągów są to %bwłaściwie ciągi yte lub ciągi dosłowne %s. Poza %formatami w pierwszym argumencie, zachowuje się on najbardziej jak %bargument w postaci łańcucha yte, z tym wyjątkiem, że nie obsługuje zmiany znaczenia \c.

printf ^%b%s$ '\n' '\n' '\t' '\t'

^
\n$^    \t$

Zobacz, dlaczego jest printflepszy niż echo? po więcej.


echo() printf


Możesz napisać własne standardy zgodne z echo...

echo(){
    printf '%b ' "$@\n\c"
}

... który właściwie powinien zawsze robić właściwe rzeczy automatycznie.

Właściwie nie ... To wypisuje literał \nna końcu argumentów, jeśli ostatni argument kończy się nieparzystą liczbą <backlashes> .

Ale to nie:

echo()
    case    ${IFS- } in
    (\ *)   printf  %b\\n "$*";;
    (*)     IFS=\ $IFS
            printf  %b\\n "$*"
            IFS=${IFS#?}
    esac

+1 za shopt -s xpg_echoopcję domyślnie echoużywaną -e.
Vignesh Raja

To rozwiązanie nie działa bez -e. Dziwi mnie, że nikt tego nie zauważył, chyba że @HaydeSchiff
ha9u63ar

@ ha9u63ar - uhh ... przeczytałeś to?
mikeserv

27

Przekaż flagę -e, aby wyświetlić echo, aby przeanalizować znaki specjalne, takie jak „\ r \ n”, na przykład:

echo -e "Line 1\r\nLine2" >> readme.txt

Fajna prosta opcja „-e”, aby uruchomić sekwencje specjalne - mówi na innej odpowiedzi, która echojest niewiarygodna i nie spełnia standardów w przeciwieństwie do printf.
Edward,

1
Upewnij się, że skrypt nie zawiera żadnych literałów \ r \ n, na przykład w tr -d "\n"poleceniu.
Noumenon

8

We wszystkich wersjach basha, których użyłem, możesz po prostu wstawić dosłownie nowy wiersz w ciągu albo interaktywnie, albo w skrypcie, pod warunkiem, że napis jest wystarczająco cytowany.

Interaktywnie:

$ echo "Line one
> Line two"
Line one
Line two
$

W skrypcie:

echo "Line one
Line two"

4
echo -e "Line 1\r\nLine2" >> readme.txt

dalsze możliwości zastosowania:

man echo

2

Ludzie już odpowiedzieli odpowiednio, ale ja nie akceptuję świata, w którym echo akceptuje każdą opcję inną niż -n.

nl='
'
echo Line 1"$nl"Line 2"$nl"Line 3

1

Jeśli masz znak, który nie jest częścią wiadomości, możesz przepuścić przez sed

$ echo "Time on the next line:@$(date +"%Y-%m-%dT%T%z")" | sed -e's/@/\n/g'
Time on the next line:
2016-03-25T10:12:39-0500
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.