从文件读取行到Bash数组

时间:2012-07-09 11:05:27

标签: arrays bash

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

到目前为止,我已尝试过以下内容:

Attempt1

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

ATTEMPT2

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

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

我正在运行bash 4.1.5

6 个答案:

答案 0 :(得分:200)

在pash 4.0中引入了

The readarray command(也拼写为mapfile)。

readarray a < /path/to/filename

答案 1 :(得分:108)

根据BinaryZebra's comment的评论进行的最新修订 和tested here。添加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's comments关于我之前尝试解决的问题

考虑到所有这些警告,我仍然在这里留下这个答案(是的,bash 4已经出了很多年了,但我记得有些mac只有2/3岁才有4级作为默认shell)

其他说明:

也可以按照下面的drizzt的建议,用

替换分叉的子shell + cat
$(</etc/passwd)

我有时使用的另一个选项是将IFS设置为XIFS,然后恢复。另请参阅Sorpigal's answer,无需担心此

答案 2 :(得分:92)

将文件的每一行读入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[@]}"

答案 3 :(得分:18)

另一种方法,如果文件包含不带空格的字符串,每行包含1个字符串:

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

fileItemArray=($fileItemString)

检查:

打印整个数组:

${fileItemArray[*]}

Length=${#fileItemArray[@]}

答案 4 :(得分:11)

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

file="somefileondisk"
lines=`cat $file`
for line in $lines; do
        echo "$line"
done

答案 5 :(得分:2)

#!/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