Dlaczego ciąg bash tutaj dodaje znak nowej linii?

34

Poniższe przykłady pokazują, że nowy ciąg jest dodawany do ciągu tutaj .
Dlaczego to się dzieje?

xxd -p <<<'a'  
# output: 610a

xxd -p <<<'a
'
# output: 610a0a
Peter.O
źródło

Odpowiedzi:

38

Prostą odpowiedzią jest to, że ksh jest napisane w ten sposób (a bash jest kompatybilny). Ale jest powód tego wyboru projektu.

Większość poleceń wymaga wprowadzania tekstu. W świecie unix plik tekstowy składa się z sekwencji wierszy, z których każda kończy się nową linią . Tak więc w większości przypadków wymagana jest ostateczna nowa linia. Szczególnie częstym przypadkiem jest chwytanie wyniku polecenia za pomocą polecenia polecenia, przetworzenie go w jakiś sposób, a następnie przekazanie do innego polecenia. Podstawienie polecenia usuwa ostatnie znaki nowej linii; <<<odkłada jeden z powrotem.

tmp=$(foo)
tmp=${tmp//hello/world}
tmp=${tmp#prefix}
bar <<<$tmp

Bash i ksh i tak nie potrafią manipulować danymi binarnymi (nie radzi sobie ze znakami zerowymi), więc nic dziwnego, że ich funkcje są ukierunkowane na dane tekstowe.

<<<Składnia tu sznurek jest przeważnie tylko dla wygody i tak, jak <<tu-dokumentów. Jeśli nie chcesz dodawać końcowej nowej linii, użyj echo -n(w bash) lub printfpotoku.

Gilles „SO- przestań być zły”
źródło
O wiele bardziej dokładna niż moja odpowiedź.
Mike
2
Bash mógł pożyczyć tutaj ciągi znaków od ksh93, ale ksh z kolei pożyczył je od zsh, które otrzymały je z pocisku Plan 9 rc .
Mark Reed,
2
<<<został wprowadzony do świata Bourne'a przez zsh, nie ksh. Został zainspirowany podobnym operatorem w porcie Unix, rcktóry nie dodał tego dodatkowego znaku nowej linii. Co ciekawe, =(<<<text)operator nie dodaje tej nowej linii do zsh.
Stéphane Chazelas
Jeśli zastanawiasz się nad zainteresowaniem tą odpowiedzią, to z powodu tego pytania w SO .
fedorqui
1
Czy jest jakiś sposób, aby napisać ciąg tutaj (bez użycia jakiegokolwiek innego narzędzia, takiego jak printfitp.), Unikając wstawiania nowej linii bash? Jak wskazano @ StéphaneChazelas jest możliwe w zsh.
CTodea
3

Jednym ze scenariuszy, w których praktyczne jest dołączanie znaków nowej linii do ciągów tutaj, jest użycie readpolecenia, gdy set -etryb jest aktywny. Przypomnijmy, że set -epowoduje zakończenie skryptu, gdy (mniej więcej) napotka instrukcje, które generują niezerowy kod statusu. Rozważ, że readgeneruje niezerowy kod stanu, gdy napotka ciąg bez znaków nowej linii:

#!/bin/bash
set -e

# The following statement succeeds because here-strings append a newline:
IFS='' read -r <<< 'newline appended'
echo 'Made it here'

# The following statement fails because 'read' returns a non-zero status
# code when no newlines are encountered.
printf 'no newline' | IFS='' read -r
echo 'Did not make it here'
Dejay Clayton
źródło
-3

Myślę, że to jedyny sposób, aby uzyskać nowy wiersz na końcu tutaj-dowód, dowód:

xxd <<<`echo -ne "a\n"`

Wygląda na to, że operator ciągu znaków usuwa nowe wiersze, chyba że podano je w przesłanej składni.

Mikrofon
źródło
4
To podstawienie polecenia usuwa ostatnią nową linię. Możesz to uprościć xxd <<<$(echo a).
Gilles „SO- przestań być zły”