29

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

示例文件:

脚本/名称.txt

alison
barb
charlie
david

脚本/script.sh

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

如何在单独的 shell 脚本中将 names.txt 文件分解为数组?

4

5 回答 5

60

一种方法是:

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

编辑: 请注意,循环在子外壳中执行,因此任何修改的变量都将是本地的,除非您declare在循环外部声明它们。

丹尼斯威廉姆森是对的。抱歉,一定是经常使用管道结构而感到困惑。

于 2012-07-05T17:59:43.330 回答
15

你会想要使用“读取”命令

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

请注意,“$name”是带引号的——如果不是,它将使用中的字符$IFS作为分隔符进行拆分。如果您只是回显变量,这可能不会被注意到,但是如果您的文件包含要复制的文件名列表,$IFS那么如果变量未引用,这些文件名将被分解,这不是您想要的或期待。

如果您想使用 Mike Clark 的方法(加载到变量中而不是使用读取),您可以不使用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

于 2012-07-05T17:59:10.750 回答
8
cat names.txt|while read line; do
    echo "$line";
done
于 2012-07-05T17:58:46.140 回答
5

我知道纯粹主义者会讨厌这种方法,但你可以cat存档。

NAMES=`cat scripts/names.txt` #names from names.txt file
for NAME in $NAMES; do
   echo "$NAME"
done
于 2012-07-05T17:58:27.293 回答
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
于 2012-07-05T19:19:07.413 回答