关于bash:将制表符分隔的文件行读入数组

Read tab-separated file line into array

我想把一个文件逐行读成一个脚本。文件中的每一行都是由一个选项卡分隔的多个值,我想将每一行读取到一个数组中。

典型的bash"逐行读取文件"示例;

1
2
3
4
while read line
do
echo $line;
done <"myfile"

但对于我来说,myfile看起来是这样的(制表符分隔的值);

1
2
value1 value2 value3
value4 value5 value6

在循环的每次迭代中,我希望每一行都进入一个数组,这样我就可以

1
2
3
4
5
6
while read line into myArray
do
 echo myArray[0]
 echo myArray[1]
 echo myArray[2]
done <"myfile"

这将在第一个循环迭代中打印以下内容;

1
2
3
value1
value2
value3

然后在第二次迭代中,它将打印

1
2
3
value4
value5
value6

这有可能吗?我能看到的唯一方法是编写一个小函数手动分解值,bash中是否有内置的支持?


你非常接近:

1
2
3
4
5
6
while IFS=$'\t' read -r -a myArray
do
 echo"${myArray[0]}"
 echo"${myArray[1]}"
 echo"${myArray[2]}"
done < myfile

(-r告诉read\在输入数据中并不特殊;-a myArray告诉它将输入行拆分为单词,并将结果存储在myArray中;IFS=$'\t'告诉它只使用制表符来拆分单词,而不是常规的bash默认值,也允许空格来拆分单词。请注意,这种方法将把一个或多个选项卡视为分隔符,因此如果任何字段为空,则后面的字段将"移位"到数组中的较早位置。没问题吧?)


如果您真的想将每个单词(bash的意思)分割成不同的数组索引,在每次while循环迭代中完全改变数组,@ruakh的答案是正确的方法。但是您可以使用read属性将每个读单词拆分成不同的变量column1column2column3,就像在这段代码中一样。

1
2
3
4
5
6
7
8
while IFS=$'\t' read -r column1 column2 column3 ; do
  printf"%b
"
"column1<${column1}>"
  printf"%b
"
"column2<${column2}>"
  printf"%b
"
"column3<${column3}>"
done <"myfile"

为了达到类似的结果,避免数组索引访问,并通过使用有意义的变量名(当然,使用columnN不是一个好主意)。


你也可以试试,

1
2
3
4
5
6
7
8
9
10
11
12
OIFS=$IFS;
IFS="\t";

animals=`cat animals.txt`
animalArray=$animals;

for animal in $animalArray
do
    echo $animal
done

IFS=$OIFS;