Il problema non è in cat
, né nel for
ciclo di per sé; è nell'uso delle virgolette. Quando scrivi:
for i in `cat file`
o (meglio):
for i in $(cat file)
o (in bash
):
for i in $(<file)
la shell esegue il comando e cattura l'output come una stringa, separando le parole dai caratteri in $IFS
. Se vuoi che le righe vengano inserite in $i
, devi giocherellare con IFS
oppure usa il while
ciclo continuo. Il while
loop è meglio se c'è il pericolo che i file elaborati siano grandi; non deve leggere l'intero file in memoria tutto in una volta, a differenza delle versioni che usano $(...)
.
IFS='
'
for i in $(<file)
do echo "$i"
done
Le virgolette attorno al "$i"
sono generalmente una buona idea. In questo contesto, con il $IFS
modificato , in realtà non è fondamentale, ma le buone abitudini sono buone abitudini anche così. Ha importanza nel seguente script:
old="$IFS"
IFS='
'
for i in $(<file)
do
(
IFS="$old"
echo "$i"
)
done
quando il file di dati contiene più spazi tra le parole:
$ cat file
abc 123, comma
the quick brown fox
jumped over the lazy dog
comma, comma
$
Uscita:
$ sh bq.sh
abc 123, comma
the quick brown fox
jumped over the lazy dog
comma, comma
$
Senza le doppie virgolette:
$ cat bq.sh
old="$IFS"
IFS='
'
for i in $(<file)
do
(
IFS="$old"
echo $i
)
done
$ sh bq.sh
abc 123, comma
the quick brown fox
jumped over the lazy dog
comma, comma
$
Puoi usare IFS
variabile a specifica si desidera una nuova riga come separatore di campo:
IFS=$'\n'
for i in `cat file`
do
echo $i
done
il ciclo for accoppiato con una modifica del separatore di campo interno (IFS) leggerà il file come previsto
per un input
abc 123, comma
the quick brown fox
jumped over the lazy dog
comma, comma
Ciclo for accoppiato con una modifica IFS
old_IFS=$IFS
IFS=$'\n'
for i in `cat file`
do
echo $i
done
IFS=$old_IFS
risulta in
abc 123, comma
the quick brown fox
jumped over the lazy dog
comma, comma