2012-07-05 48 views
27

可能重复:
Looping through the content of a file in Bash?如何使用shell遍历外部文件中的行?

我有一个文件,名称的列表。我需要使用shell脚本从外部文件中遍历该文件中的所有名称。我怎样才能做到这一点?

实施例的文件:

脚本/ names.txt中

alison 
barb 
charlie 
david 

脚本/ script.sh

NAMES="" #names from names.txt file 
for NAME in $NAMES; do 
    echo "$NAME" 
done 

我怎样才能爆炸文件names.txt到一个数组中的单独shell脚本?

+1

如何链接到原来的Q&A? – bearvarine 2015-09-28 16:17:36

回答

54

一种方式的价值是:

while read NAME 
do 
    echo "$NAME" 
done < names.txt 

编辑: 注意循环获取一个子执行shell,因此任何修改的变量都将是本地的,除非您在循环之外声明 declare

丹尼斯威廉姆森是正确的。对不起,我们必须经常使用管道构造并且感到困惑。

+2

不,因为没有任何东西被传入'while',所以没有子外壳。重定向到'done'不会创建一个子shell。 – 2012-07-05 18:24:46

+0

顺便说一下,使用korn shell(但使用pdksh)不会发生管道问题(bug?)。 – cdarke 2012-07-06 08:12:52

5

我知道纯粹主义者会讨厌这种方法,但你可以用cat这个文件。

NAMES=`cat scripts/names.txt` #names from names.txt file 
for NAME in $NAMES; do 
    echo "$NAME" 
done 
+5

这具有不调用子shell的优点,但会考虑'names.txt'中的任何空格作为分隔符。 – smocking 2012-07-05 18:01:21

+2

“纯粹主义者”也会帮助解释这个问题。有多个问题。读线时请参阅http://mywiki.wooledge.org/DontReadLinesWithFor – tripleee 2017-03-13 12:41:57

6
cat names.txt|while read line; do 
    echo "$line"; 
done 
+4

';做...;完成 2012-07-05 18:11:51

13

你会想要使用“读”命令

while read name 
do 
    echo "$name" 
done < names.txt 

注意,“$名”引述 - 如果它不是,它会使用字符分割在$IFS作为分隔符。如果你只是回显变量,这可能不会被注意到,但是如果你的文件包含你想要复制的文件名列表,如果变量没有被引用,这些将被分解$IFS,这不是你想要或期望。

如果你想使用麦克·克拉克的做法(加载到一个变量,而不是使用读),你可以做到这一点,而无需使用cat

NAMES="$(< scripts/names.txt)" #names from names.txt file 
for NAME in $NAMES; do 
    echo "$NAME" 
done 

这样做的问题在于,它加载整个文件转换为$NAMES,当您将其读回时,您可以获取整个文件(如果带有引号)或将文件分解为$IFS(如果未引用)。默认情况下,这会给你个别的单词,而不是单独的行。所以如果名字“Mary Jane”出现在一行中,你会将“Mary”和“Jane”作为两个独立的名字。使用read会解决这个问题......虽然你也可以改变的$IFS

2

这可能会为你工作:

cat <<\! >names.txt 
> alison 
> barb 
> charlie 
> david 
> ! 
OIFS=$IFS; IFS=$'\n'; NAMES=($(<names.txt)); IFS=$OIFS 
echo "${NAMES[@]}" 
alison barb charlie david 
echo "${NAMES[0]}" 
alison 
for NAME in "${NAMES[@]}";do echo $NAME;done 
alison 
barb 
charlie 
david