Zgodnie z poniższym przykładem i moim ostatnim pytaniem In bash, gdzie zniknął znak końca nowej linii? Chcę wiedzieć, dlaczego tak się dzieje
x="$(echo -ne "a\nb\n")" ; echo -n "$x" | xxd -p
# Output is: 610a62
# The trailing newline from the 'echo' command
# has been "deleted" by Command Substitution
Zakładam, że musi istnieć jakiś bardzo ważny powód akcji powłoki, mianowicie Zastąpienie polecenia, aby faktycznie usunąć niektóre dane z wyjściowego polecenia, które zastępuje ...
ale nie mogę się tym zająć, ponieważ wydaje się, że tak jest antyteza tego, co ma robić ... tj. przekazać wyjście polecenia z powrotem do procesu skryptu ... Wstrzymywanie jednego znaku wydaje mi się dziwne, ale przypuszczam, że jest rozsądny powód ... Chcę dowiedzieć się, co to za powód ... .
Odpowiedzi:
Ponieważ powłoka nie była pierwotnie zamierzana jako pełny język programowania.
Trudno jest usunąć znak końcowy
\n
z niektórych danych wyjściowych polecenia. Jednak do celów wyświetlania prawie wszystkie polecenia kończą swój wynik\n
, więc… musi istnieć prosty sposób na usunięcie go, gdy chcesz go użyć w innym poleceniu.$()
Wybrano automatyczne usuwanie z konstrukcją.Może więc zaakceptujesz to pytanie jako odpowiedź:
Czy możesz znaleźć prosty sposób na usunięcie końcowego,
\n
jeśli nie zostało to zrobione automatycznie w poniższym poleceniu?Należy pamiętać, że cytowanie jest wymagane, aby zapobiec rozbiciu podwójnych spacji, które mogą pojawić się w sformatowanych datach.
źródło
shopt
potrzeba zmiany opisanego domyślnego zachowania, byłbym szczęśliwy ponownie ... Trudno mi myśleć, że Bash / Linux / Unix skaziłby tak krytyczną funkcję, jak „przechwytywanie standardowego” tylko dlatego,date
że nie ma a z opcją / bez „\ n” ... Oczywistym rozwiązaniem byłoby to, że bash (lub inna powłoka) mashopt
do tego ... Czy znasz jakieś? .. i czy masz jakieś odnośniki, które mówią o tym, dlaczego i dlaczego ten problem? ... i dlaczego niedate
ma opcji \ n .. Powinno!$()
składni alternatywnej.{ echo -n "The current date is "; var="$(date; echo -e x)"; var="${var%x}"; echo -n "$var"; echo ", have a good day!"; }
.. niech tak będzie :)date
by działało, ale użyłem tylkodate
jako przykładu dowolnego polecenia ..Jest to część standardu :
Oczywiście norma jest prawdopodobnie napisana w ten sposób, ponieważ tak to
ksh
zrobiło czy coś, ale jest to standard i jest to udokumentowane zachowanie. Jeśli ci się nie podoba, użyj Perla lub czegoś innego, co pozwoli ci zachować końcowe znaki nowej linii.źródło
To ma dla mnie sens. Nowa linia jest tylko na pierwszym miejscu, w normalnym wyjściu polecenia, tak że monit pojawia się po zakończeniu polecenia w nowym wierszu. Nowa linia w większości przypadków nie jest częścią oryginalnego wyjścia, służy do uporządkowania ekranu. Podczas analizowania danych wyjściowych polecenia nowy wiersz na końcu jest zwykle kłopotliwy. Dlaczego
wc
polecenie wyświetla 2 wiersze tekstu? Och, nie, wyprowadza jeden, po którym następuje nowa linia. Kiedy parsujeszwc
, nie chcesz się martwić, że istnieją 2 linie wyjściowe - tak naprawdę nie ma, jest tylko jedna.źródło
\n
w oryginalnymstdout
strumieniu jest usuwany przez zastąpienie polecenia. to znaczy. moje oryginalne dane (bardzo ważne dane) usunęły końcowe znaki nowej linii, nawet jeśli dane są zawinięte w „cudzysłowy”. Rozumiem, jak i dlaczego Dzielenie słów działa, ale absolutnie nie mam pojęcia, dlaczego zastępowanie poleceń usuwa tylko nowe wiersze i tylko końcowe .Napotkałem ten sam problem i znalazłem poniższy przykład. Wydaje się, że zacytowanie pomogło tej sytuacji, a przynajmniej zrobiło to dla mnie:
http://tldp.org/LDP/abs/html/commandsub.html .
źródło
$str
zawierającą ciąg"a b c"
. Jeśli przejdzie$str
doecho
bez cudzysłowów (echo $str
),echo
otrzymaa
,b
ic
jako trzy oddzielne argumenty. Twoja powłoka nie dba o odstępy między argumentami.echo
wypisze te argumenty ze spacjami oddzielającymi każdy, więc otrzymujesz"a b c"
. Jeśli przekażesz zmiennąecho
z cudzysłowami wokół niej (echo "$str"
), powłoka zobaczy ją jako jeden argument iecho
odbierze ją jako taką, dzięki czemu białe znaki nie zostaną zwinięte. To samo dotyczy znaków nowej linii.-n
flagi,echo
dodaje znak wyjściowy nowej linii, więc oba echa w twoim przykładzie mają końcowe znaki nowej linii. Jeśli jednak spróbujeszecho -n $dir_listing
lubecho -n "$dir_listing"
, zobaczysz, że nie ma drukowanego znaku nowej linii z cudzysłowami lub bez nich$dir_listing
, co sugeruje, że problem dotyczy substytucji polecenia.dlaczego
echo "hello "
(bez cudzysłowów) pożera przestrzeń? wartość znaków IFS jest postrzegana przez powłokę jako ograniczniki, dlatego końcowe znaki (które niczego nie ograniczają) są usuwane. podstawienie polecenia jest po prostu wykonaniem polecenia w podpowłoce, więc jest zgodne z tą samą logiką.źródło
x="hello "
ix="hello "
stracą wszystkie spacje końcowe, jeśli są wyświetlane przezecho $x
... Jednak tylko ostatnia nowa linia zastępowania polecenia zostanie utracona.IFS
nie ma nic wspólnego z usuwaniem nowych linii na końcu podstawiania poleceń.