Ce qui doit être expliqué est que la commande semble fonctionner, pas son code de sortie
'\n'
est composé de deux caractères: une barre oblique inverse \et une lettre n. Ce dont vous pensiez avoir besoin, c'était d' $'\n'
un saut de ligne (mais ce ne serait pas bien non plus, voir ci-dessous).
L' -d
option fait ceci:
-d delim continue until the first character of DELIM is read, rather
than newline
Donc, sans cette option, read
lirait jusqu'à une nouvelle ligne, diviserait la ligne en mots en utilisant les caractères $IFS
comme séparateurs et placerait les mots dans le tableau. Si vous spécifiez -d $'\n'
, en définissant le délimiteur de ligne sur une nouvelle ligne, cela ferait exactement la même chose . Le réglage -d '\n'
signifie qu'il sera lu jusqu'à la première barre oblique inverse (mais, encore une fois, voir ci-dessous), qui est le premier caractère de delim
. Puisqu'il n'y a pas de barre oblique inverse dans votre fichier, le read
se terminera à la fin du fichier et:
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.
C'est pourquoi le code de sortie est 1.
Du fait que vous pensez que la commande a fonctionné, nous pouvons conclure qu'il n'y a pas d'espaces dans le fichier, de sorte qu'après read
avoir lu l'intégralité du fichier dans l'espoir futile de trouver une barre oblique inverse, il sera divisé par des espaces (la valeur par défaut de $IFS
), y compris les sauts de ligne. Ainsi, chaque ligne (ou chaque mot, si une ligne contient plusieurs mots) est stockée dans le tableau.
Le cas mystérieux de la barre oblique inversée
Maintenant, comment savais-je que le fichier ne contenait aucune barre oblique inverse? Parce que vous n'avez pas fourni le -r
drapeau à read
:
-r do not allow backslashes to escape any characters
Donc, si vous aviez des barres obliques inverses dans le fichier, elles auraient été supprimées, à moins que vous n'en ayez deux de suite. Et, bien sûr, il y a des preuves qui read
avaient un code de sortie de 1, ce qui démontre qu'il n'a pas trouvé de barre oblique inverse, donc il n'y en avait pas deux de suite non plus.
Plats à emporter
Bash ne serait pas bash s'il n'y avait pas de pièges cachés derrière à peu près toutes les commandes, et read
ne fait pas exception. En voici deux:
Sauf indication contraire -r
, read
interprètera les séquences d'échappement de barre oblique inverse. À moins que ce ne soit réellement ce que vous voulez (ce qui est occasionnellement, mais seulement occasionnellement), vous devez vous rappeler de spécifier -r
pour éviter que les caractères disparaissent dans les rares cas où il y a des barres obliques inverses dans l'entrée.
Le fait que read
renvoie un code de sortie de 1 ne signifie pas qu'il a échoué. Il a peut-être bien réussi, sauf pour trouver le terminateur de ligne. Soyez donc prudent avec une boucle comme celle-ci: while read -r LINE; do something with LINE; done
car elle échouera do something
avec la dernière ligne dans le cas rare où la dernière ligne n'a pas de nouvelle ligne à la fin.
read -r LINE
conserve les barres obliques inverses, mais ne préserve pas les espaces de début ou de fin.
while read
". Sinon, réponse fantastique.while read
tant que vous n'avez rien dans la boucle. Sinon, c'est un insecte qui attend de vous mordre - et croyez-moi, j'ai été mordu.read
.mapfile
c'est plutôt cool. Pour un hack rapide et sale, j'utiliserai la boucle while interdite, mais j'ai arrêté de mettre cela dans les scripts de production. YMMV et moi avons adouci l'avertissement dans la réponse.C'est le comportement attendu:
la source