Poniższy kod najlepiej opisuje sytuację. Dlaczego ostatni wiersz nie wyświetla końcowego znaku nowej linii? Wynik każdego wiersza jest pokazany w komentarzu. Używam GNU bash, wersja 4.1.5
echo -n $'a\nb\n' | xxd -p # 610a620a
x=$'a\nb\n' ; echo -n "$x" | xxd -p # 610a620a
echo -ne "a\nb\n" | xxd -p # 610a620a
x="$(echo -ne "a\nb\n")" ; echo -n "$x" | xxd -p # 610a62
tmp=$(somecommand; echo a); tmp=${tmp%a}
tmp=$(somecommand; echo a)
... To z pewnością doprowadziło do sedna sprawy ... Dopóki nie zobaczyłem przykładu, moja tendencja nadal byłaby wykorzystywanaecho -n a
... ale oczywiście !, nie ma potrzeby-n
, ponieważ Komenda Zmiana usunie wprowadzony spływu przełamane w każdym razie! ... dzięki ...Odpowiedzi:
Funkcja podstawiania poleceń
$()
(i jej kuzyn backstick) specjalnie usuwa końcowe znaki nowej linii. Jest to udokumentowane zachowanie i zawsze powinieneś być tego świadomy podczas korzystania z konstrukcji.Nowe linie w treści tekstu nie są usuwane przez operator podstawiania, ale mogą być również usuwane podczas dzielenia słów na powłoce, więc to, jak się to okaże, zależy od tego, czy użyłeś cudzysłowów, czy nie. Zwróć uwagę na różnicę między tymi dwoma zastosowaniami:
W drugim przykładzie wynik nie był cytowany, a nowy wiersz został zinterpretowany jako podział na słowa, dzięki czemu pojawił się na wyjściu jako spacja!
źródło
Podczas korzystania z podstawiania poleceń powłoka wykonuje polecenia w podpowłoce, zwracając swoje standardowe wyjście. w tym procesie znaki IFS tracą swoje znaczenie (jeśli nie są cytowane), ponieważ polecenie zwraca zwykłe słowa podzielone, więc końcowe są usuwane. Na przykład:
i bardziej praktycznie
pwd
będzie działać, nawet jeśli nazwa katalogu ma między sobą nowy wiersz, ale$(pwd)
nie zadziała.Zwykłym obejściem jest dodanie czegoś na końcu polecenia i usunięcie go później.
źródło
echo "$(echo -e '\n')" | wc
, który wyprowadza1 0 1
, w porównaniu do2 0 2
$(pwd)
i"$(pwd)"
, patrz odpowiedź Caleba.