Perché bash rimuove \ n in $ (file cat)?


24

Se ho il file input.txtcontenente:

hello
world
!

Quindi eseguendo il comando bash echo $(cat input.txt)verrà generato questo:

hello world !

Perché e come posso risolverlo per generare esattamente ciò che è nel file come è nel file?

Risposte:


32

Se usi

echo "$(cat input.txt)"

funzionerà correttamente.

Probabilmente l'input di eco è separato da newline e lo gestirà come comandi separati, quindi il risultato sarà senza newline.


Bello! Quindi qual è la differenza (se presente) tra $ () e i backtick? (Scusate se questo è troppo tangenziale)
Chan-Ho Suh

Sono equivalenti, tranne per il fatto che $ (...) è più facile da annidare. In entrambi i casi, se non citate il risultato, questo verrà tokenizzato in più argomenti su uno spazio bianco.
James Henstridge,

3
Ma l' ultimo carattere di nuova riga viene omesso, anche tra virgolette doppie. Al contrario, l'operatore backtick di Perl si espande all'intero output del comando, comprese tutte le nuove righe.
Keith Thompson,

6
@KeithThompson sì, la sostituzione dei comandi rimuove tutte le nuove righe finali dall'output. Ciò ha il vantaggio, ad esempio, di echo "$(date) something"rimuovere la nuova riga finale dall'output della data, facendo in modo che l'eco produca la data e "qualcosa" sulla stessa riga. Se è necessario memorizzare un file o l'output del comando "così com'è", utilizzare mapfile ( help mapfile) read -rd ''o un ciclo di lettura while.
geirha,

Grazie a tutti :-) Ho imparato qualcosa da ogni commento qui!
Chan-Ho Suh,

2

Citato dalla pagina del manuale di bash, sezione Command Substitution:

Le nuove righe incorporate non vengono eliminate, ma possono essere rimosse durante la divisione delle parole.

Un po 'più avanti, stessa sezione:

Se la sostituzione appare tra virgolette doppie, la divisione delle parole e l'espansione del percorso non vengono eseguite sui risultati.

Ecco perché echo "$(cat /etc/passwd)" funziona.

Inoltre, si dovrebbe essere consapevoli del fatto che la sostituzione dei comandi secondo le specifiche POSIX rimuove le nuove righe finali:

$ echo "$(printf "one\ntwo\n\n\n")"
one
two

Pertanto, l'output di un file tramite $(cat file.txt)può portare alla perdita di nuove righe finali e ciò può costituire un problema se l'integrità dell'intero file è prioritaria.


2

È possibile conservare le nuove righe, ad esempio impostando IFS su vuoto:

$ IFS=
$ a=$(cat links.txt)
$ echo "$a"
link1
link2
link3
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.