El problema no está en cat
, ni en el for
bucle per se; está en el uso de comillas inversas. Cuando escribes:
for i in `cat file`
o (mejor):
for i in $(cat file)
o (en bash
):
for i in $(<file)
el shell ejecuta el comando y captura la salida como una cadena, separando las palabras en los caracteres en $IFS
. Si desea ingresar líneas a $i
, tienes que jugar con IFS
o usa el while
círculo. El while
loop es mejor si existe algún peligro de que los archivos procesados sean grandes; no tiene que leer todo el archivo en la memoria de una sola vez, a diferencia de las versiones que usan $(...)
.
IFS='
'
for i in $(<file)
do echo "$i"
done
Las comillas alrededor del "$i"
son generalmente una buena idea. En este contexto, con el $IFS
modificado , en realidad no es crítico, pero los buenos hábitos son buenos hábitos aun así. Importa en el siguiente script:
old="$IFS"
IFS='
'
for i in $(<file)
do
(
IFS="$old"
echo "$i"
)
done
cuando el archivo de datos contiene múltiples espacios entre palabras:
$ cat file
abc 123, comma
the quick brown fox
jumped over the lazy dog
comma, comma
$
Salida:
$ sh bq.sh
abc 123, comma
the quick brown fox
jumped over the lazy dog
comma, comma
$
Sin las comillas dobles:
$ 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
$
Puedes usar IFS
variable para especificar si desea una nueva línea como separador de campo:
IFS=$'\n'
for i in `cat file`
do
echo $i
done
el bucle for junto con un cambio del separador de campo interno (IFS) leerá el archivo según lo previsto
para una entrada
abc 123, comma
the quick brown fox
jumped over the lazy dog
comma, comma
Bucle for junto con un cambio de IFS
old_IFS=$IFS
IFS=$'\n'
for i in `cat file`
do
echo $i
done
IFS=$old_IFS
da como resultado
abc 123, comma
the quick brown fox
jumped over the lazy dog
comma, comma