Ciò che deve essere spiegato è che il comando sembrava funzionare, non il suo codice di uscita
'\n'
è composto da due personaggi: una barra rovesciata \e una lettera n. Quello che pensavi di aver bisogno era $'\n'
, che è un avanzamento di riga (ma non sarebbe neanche giusto, vedi sotto).
L' -d
opzione fa questo:
-d delim continue until the first character of DELIM is read, rather
than newline
Quindi, senza quell'opzione, read
leggerebbe una nuova riga, dividere la riga in parole usando i caratteri $IFS
come separatori e metterebbe le parole nella matrice. Se specificato -d $'\n'
, impostando il delimitatore di linea su una nuova riga, farebbe esattamente la stessa cosa . L'impostazione -d '\n'
significa che leggerà fino alla prima barra rovesciata (ma, ancora una volta, vedi sotto), che è il primo carattere in delim
. Poiché non è presente una barra rovesciata nel file, read
verrà terminato alla fine del file e:
Exit Status:
The return code is zero, unless end-of-file is encountered, read times out,
or an invalid file descriptor is supplied as the argument to -u.
Ecco perché il codice di uscita è 1.
Dal fatto che ritieni che il comando abbia funzionato, possiamo concludere che non ci sono spazi nel file, in modo che read
, dopo aver letto l'intero file nella futile speranza di trovare una barra rovesciata, lo divida per spazi bianchi (il valore predefinito di $IFS
), comprese le newline. Quindi ogni riga (o ogni parola, se una riga contiene più di una parola) viene inserita nell'array.
Il misterioso caso della contraccolpo violenta
Ora, come sapevo che il file non conteneva barre rovesciate? Perché non hai fornito la -r
bandiera a read
:
-r do not allow backslashes to escape any characters
Quindi se avessi delle barre rovesciate nel file, sarebbero state rimosse, a meno che tu non ne avessi due di fila. E, naturalmente, ci sono prove che read
avevano un codice di uscita 1, il che dimostra che non ha trovato una barra rovesciata, quindi non ce n'erano neanche due di fila.
Asporto
Bash non farebbe schifo se non ci fossero nascondigli dietro quasi tutti i comandi, e read
non fa eccezione. Eccone un paio:
Se non specificato -r
, read
interpreterà le sequenze di escape con barra rovesciata. A meno che non sia effettivamente quello che vuoi (che è occasionalmente, ma solo occasionalmente), dovresti ricordare di specificare -r
di evitare la scomparsa dei caratteri nel raro caso in cui ci siano barre rovesciate nell'input.
Il fatto che read
restituisca un codice di uscita pari a 1 non significa che sia fallito. Potrebbe esserci riuscito, tranne per trovare il terminatore di linea. Quindi fai attenzione con un ciclo come questo: while read -r LINE; do something with LINE; done
perché non riuscirà do something
con l'ultima riga nel raro caso in cui l'ultima riga non ha una riga alla fine.
read -r LINE
conserva le barre rovesciate, ma non conserva gli spazi bianchi iniziali o finali.