Problém není v cat
, ani v for
smyčka jako taková; je to v použití zpětných uvozovek. Když napíšete buď:
for i in `cat file`
nebo (lépe):
for i in $(cat file)
nebo (v bash
):
for i in $(<file)
shell provede příkaz a zachytí výstup jako řetězec oddělující slova u znaků v $IFS
. Pokud chcete, aby řádky vstupovaly do $i
, buď si musíte pohrát s IFS
nebo použijte while
smyčka. while
smyčka je lepší, pokud existuje nebezpečí, že zpracovávané soubory budou velké; nemusí číst celý soubor do paměti najednou, na rozdíl od verzí používajících $(...)
.
IFS='
'
for i in $(<file)
do echo "$i"
done
Uvozovky kolem "$i"
jsou obecně dobrý nápad. V této souvislosti s upraveným $IFS
, ve skutečnosti to není kritické, ale dobré návyky jsou dobré návyky i tak. Na tom záleží v následujícím skriptu:
old="$IFS"
IFS='
'
for i in $(<file)
do
(
IFS="$old"
echo "$i"
)
done
když datový soubor obsahuje více mezer mezi slovy:
$ cat file
abc 123, comma
the quick brown fox
jumped over the lazy dog
comma, comma
$
Výstup:
$ sh bq.sh
abc 123, comma
the quick brown fox
jumped over the lazy dog
comma, comma
$
Bez dvojitých uvozovek:
$ 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
$
Můžete použít IFS
proměnná na konkrétní chcete jako oddělovač polí nový řádek:
IFS=$'\n'
for i in `cat file`
do
echo $i
done
smyčka for spojená se změnou interního oddělovače polí (IFS) přečte soubor podle plánu
pro vstup
abc 123, comma
the quick brown fox
jumped over the lazy dog
comma, comma
Pro smyčku ve spojení se změnou IFS
old_IFS=$IFS
IFS=$'\n'
for i in `cat file`
do
echo $i
done
IFS=$old_IFS
výsledky v
abc 123, comma
the quick brown fox
jumped over the lazy dog
comma, comma