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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9736202/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 21:48:00  来源:igfitidea点击:

Read tab-separated file line into array

arraysbash

提问by jwbensley

I would like to read a file into a script, line by line. Each line in the file is multiple values separated by a tab, I'd like to read each line into an array.

我想将文件逐行读入脚本。文件中的每一行都是由制表符分隔的多个值,我想将每一行读入一个数组。

Typical bash "read file by line" example;

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

while read line
do
echo $line;
done < "myfile"

For me though, myfile looks like this (tab separated values);

不过对我来说,myfile 看起来像这样(制表符分隔值);

value1 value2 value3
value4 value5 value6

On each iteration of the loop, I'd like each line to go into an array so I can

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

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

This would print the following on the first loop iteration;

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

value1
value2
value3

Then on the second iteration it would print

然后在第二次迭代它会打印

value4
value5
value6

Is this possible? The only way I can see is to write a small function to break out the values manually, is there built in support in bash for this?

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

回答by ruakh

You're very close:

你非常接近:

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

(The -rtells readthat \isn't special in the input data; the -a myArraytells it to split the input-line into words and store the results in myArray; and the IFS=$'\t'tells it to use only tabs to split words, instead of the regular Bash default of also allowing spaces to split words as well. Note that this approach will treat one or moretabs as the delimiter, so if any field is blank, later fields will be "shifted" into earlier positions in the array. Is that O.K.?)

(该-r告诉read那个\是不是在输入数据的特殊;在-a myArray告诉它拆分输入行成文字并存储在结果myArray;以及IFS=$'\t'告诉它仅使用标签来分的话,不是也经常猛砸默认也允许空格分割单词。请注意,这种方法会将一个或多个制表符视为分隔符,因此如果任何字段为空白,则后面的字段将“移”到数组中较早的位置。这样可以吗?)

回答by slylittl3

If you really want to split every word (bash meaning) into a different array index completely changing the array in every while loop iteration, @ruakh's answer is the correct approach. But you can use the read property to split every read word into different variables column1, column2, column3like in this code snippet

如果您真的想将每个单词(bash 含义)拆分为不同的数组索引,在每次 while 循环迭代中完全改变数组,@ruakh 的答案是正确的方法。但是你可以使用读取属性每读字拆分成不同的变量column1column2column3在此代码段像

while IFS=$'\t' read -r column1 column2 column3 ; do
  printf "%b\n" "column1<${column1}>"
  printf "%b\n" "column2<${column2}>"
  printf "%b\n" "column3<${column3}>"
done < "myfile"

to reach a similar result avoiding array index access and improving your code readability by using meaningful variable names (of course using columnNis not a good idea to do so).

通过使用有意义的变量名来避免数组索引访问并提高代码可读性(当然使用columnN不是一个好主意)来达到类似的结果。

回答by Dinuksha Samanage

You could also try,

你也可以试试,

OIFS=$IFS;
IFS="\t";

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

for animal in $animalArray
do
    echo $animal
done

IFS=$OIFS;