85 votes

Utilisez Bash pour lire ligne par ligne et conserver les espaces.

Lorsque j'utilise "cat test.file", il affiche

1
 2
  3
   4

Quand j'utilise le fichier Bash,

cat test.file |
while read data
do
    echo "$data"
done

Il montrera

1
2
3
4

Comment faire pour que le résultat soit identique à celui du fichier de test original ?

0 votes

On peut trouver une ligne script utile pour faire précéder les numéros de ligne de stdio : { i=0; while read; do i=$(dc 1 $i + p); printf "%4 d $REPLY\n" $i; done; } Il est compatible avec l'ancien SH.

129voto

DigitalRoss Points 80400
IFS=''
cat test.file |
while read data
do
    echo "$data"
done

Je réalise que vous avez peut-être simplifié l'exemple à partir de quelque chose qui avait vraiment besoin d'un pipeline, mais avant que quelqu'un d'autre ne le dise :

IFS=''
while read data; do
    echo "$data"
done < test.file

1 votes

Parce que le script lit une seule variable par ligne, tous les espaces dans les données (après le premier non-blanc) sont préservés quoi qu'il en soit. Mais l'IFS vide préserve les espaces de tête (dans ksh et bash).

30 votes

C'est un endroit où vous pourriez écrire while IFS= read data; ...

0 votes

Je commençais à essayer export IFS ..., bon je vous lis conseil !

33voto

Joshua Davies Points 883

En fait, si vous ne fournissez pas d'argument à l'appel "read", read définira une variable par défaut appelée $REPLY qui préservera les espaces. Donc vous pouvez simplement faire ceci :

$ cat test.file | while read; do echo "$REPLY"; done

2 votes

Cette réponse m'a incité à lire attentivement la documentation de l'application read .

3 votes

Notez que si vous avez des caractères antislash tels que \n dans votre fichier source (c'est-à-dire le code source), read les convertira en juste n . Utilisez read -r pour éviter cela.

1 votes

Notez que cette $REPLY ne fonctionne pas dans ZSH, mais la solution IFS= read La solution fonctionne à la fois dans ZSH et dans Bash.

4voto

diogovk Points 358

Juste pour compléter la réponse de DigitalRoss.

Dans le cas où vous souhaitez modifier le IFS juste pour cette commande, vous pouvez utiliser des parenthèses. Si vous le faites, la valeur de IFS sera modifiée uniquement à l'intérieur du sous-shell. Comme ceci :

echo '  word1
  word2' |  ( IFS='' ; while read line ; do echo "$line" check ; done ; )

La sortie sera (en conservant les espaces) :

  word1 check
  word2 check

0 votes

Même si l IFS a déjà sauvé cet exemple particulier, vous devriez quand même citer "$line" . Dans un exemple concret, la valeur peut toujours contenir des caractères génériques de l'interpréteur de commandes et autres.

3 votes

Mauvais Donc, downvoted ! Utilisez IFS='' read -r line à la place ! Dans votre exemple, le Pipe exécute le {..} dans une sous-couche ! Comme IFS=' '; ( IFS='' ); echo "=$IFS=" qui imprime = = (voir la CPS). En revanche IFS=' '; { IFS=''; }; echo "=$IFS=" imprime == (IFS de l'intérieur {..} ). Cependant, je recommande plutôt : fullread() { local IFS=''; read -r $1; } o IFS='' read -r line (il n'y a pas de ;' between IFS=''` et read . Dans les coquillages VAR=val cmd args.. permet de modifier l'environnement pour une seule commande (cela fonctionne pour les modules intégrés tels que read aussi).

1 votes

Je ne suis pas sûr de suivre, Tino. Essayez cat -etv <<<"$IFS" ; echo word1 | { IFS=''; cat -etv <<<"$IFS" ; } ; cat -etv <<<"$IFS" ; . Le subshell n'a pas modifié l'IFS en dehors du bloc comme je m'y attendais. Pouvez-vous nous en dire plus ?

2voto

plhn Points 424

Peut-être IFS est le point clé comme d'autres l'ont dit. Vous devez ajouter seulement IFS= entre while y read .

cat test.file | 
while IFS= read data 
 do echo "$data"
 done

et n'oubliez pas les citations de $data sinon echo coupera les espaces.

Mais comme Joshua Davies a mentionné vous préférez utiliser la variable prédéfinie $REPLY .

0voto

Mu Qiao Points 3199

read data divisera les données par _IFS_ qui est généralement " \t\n ". Cela permettra de conserver les blancs pour vous :

var=$(cat test.file)
echo "$var"

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X