241

我正在尝试将包含行的文件读入 Bash 数组。

到目前为止,我已经尝试了以下方法:

尝试1

a=( $( cat /path/to/filename ) )

尝试2

index=0
while read line ; do
    MYARRAY[$index]="$line"
    index=$(($index+1))
done < /path/to/filename

两次尝试都只返回一个包含文件第一行的元素数组。我究竟做错了什么?

我正在运行 bash 4.1.5

4

6 回答 6

347

readarray命令(也拼写为mapfile)是在 bash 4.0 中引入的。

readarray -t a < /path/to/filename
于 2012-07-09T12:38:41.527 回答
141

最新版本基于BinaryZebra 的评论在此处测试。添加command eval允许将表达式保留在当前执行环境中,而之前的表达式仅在 eval 期间保留。

使用没有空格\制表符的 $IFS,只有换行符/CR

$ IFS=$'\r\n' GLOBIGNORE='*' command eval  'XYZ=($(cat /etc/passwd))'
$ echo "${XYZ[5]}"
sync:x:5:0:sync:/sbin:/bin/sync

另请注意,您可能将数组设置得很好,但读错了 - 请务必使用双引号""和大括号{},如上例所示


编辑:

请注意关于可能的全局扩展的评论中关于我的回答的许多警告,特别是gniourf-gniourf对我之前尝试解决的评论

考虑到所有这些警告,我仍然将这个答案留在这里(是的,bash 4 已经存在很多年了,但我记得一些只有 2/3 年历史的 Mac 将 pre-4 作为默认 shell)

其他注意事项:

也可以按照下面 drizzt 的建议,将分叉的 subshel​​l+cat 替换为

$(</etc/passwd)

我有时使用的另一个选项是将 IFS 设置为 XIFS,然后再恢复。另请参阅Sorpigal 的答案,不需要为此烦恼

于 2012-07-09T11:10:02.027 回答
136

将文件的每一行读入bash数组的最简单方法是:

IFS=$'\n' read -d '' -r -a lines < /etc/passwd

现在只需索引数组lines即可检索每一行,例如

printf "line 1: %s\n" "${lines[0]}"
printf "line 5: %s\n" "${lines[4]}"

# all lines
echo "${lines[@]}"
于 2012-07-09T11:20:55.977 回答
25

如果文件包含没有空格且每行 1 个字符串的字符串,则另一种方法是:

fileItemString=$(cat  filename |tr "\n" " ")

fileItemArray=($fileItemString)

查看:

打印整个数组:

${fileItemArray[*]}

Length=${#fileItemArray[@]}
于 2013-10-21T12:47:30.840 回答
23

你的第一次尝试很接近。这是使用您的想法的简单方法。

file="somefileondisk"
lines=`cat $file`
for line in $lines; do
        echo "$line"
done
于 2015-05-29T17:51:23.007 回答
4
#!/bin/bash
IFS=$'\n' read  -d '' -r -a inlines  < testinput
IFS=$'\n' read  -d '' -r -a  outlines < testoutput
counter=0
cat testinput | while read line; 
do
    echo "$((${inlines[$counter]}-${outlines[$counter]}))"
    counter=$(($counter+1))
done
# OR Do like this
counter=0
readarray a < testinput
readarray b < testoutput
cat testinput | while read myline; 
do
    echo value is: $((${a[$counter]}-${b[$counter]}))
    counter=$(($counter+1))
done
于 2014-04-18T19:35:00.760 回答