在Bash中从文本文件创建数组

时间:2015-06-22 19:50:12

标签: arrays bash loops scripting variable-assignment

脚本获取URL,解析所需字段,并将其输出重定向以保存在文件 file.txt 中。每次找到字段时,输出都会保存在新行中。

file.txt的

A Cat
A Dog
A Mouse 
etc... 

我想取file.txt并在新脚本中创建一个数组,其中每一行都是数组中自己的字符串变量。到目前为止,我已经尝试过:

#!/bin/bash

filename=file.txt
declare -a myArray
myArray=(`cat "$filename"`)

for (( i = 0 ; i < 9 ; i++))
do
  echo "Element [$i]: ${myArray[$i]}"
done

当我运行此脚本时,空白会导致单词被分割而不是

期望的输出

Element [0]: A Cat 
Element [1]: A Dog 
etc... 

我最终得到了这个:

实际输出

Element [0]: A 
Element [1]: Cat 
Element [2]: A
Element [3]: Dog 
etc... 

如何调整下面的循环,使每行上的整个字符串与数组中的每个变量一一对应?

6 个答案:

答案 0 :(得分:71)

使用mapfile命令:

mapfile -t myArray < file.txt

错误正在使用for - 循环文件的的惯用方法是:

while IFS= read -r line; do echo ">>$line<<"; done < file.txt

有关详细信息,请参阅BashFAQ/005

答案 1 :(得分:7)

Bash版本4及更高版本中提供了

mapfilereadarray(它们是同义词)。如果您有旧版本的Bash,则可以使用循环将文件读入数组:

arr=()
while IFS= read -r line; do
  arr+=("$line")
done < file

如果文件的最后一行有不完整的(缺少换行符),您可以使用以下替代方法:

arr=()
while IFS= read -r line || [[ "$line" ]]  do
  arr+=("$line")
done < file

相关:

答案 2 :(得分:6)

您也可以这样做:

oldIFS="$IFS"
IFS=$'\n' arr=($(<file))
IFS="$oldIFS"
echo "${arr[1]}" # It will print `A Dog`.

注意:

仍然会发生文件名扩展。例如,如果有一个文字*的行,它将扩展到当前文件夹中的所有文件。因此,只有当您的文件没有这种情况时才使用它。

答案 3 :(得分:4)

您可以简单地从文件中读取每一行并将其分配给数组。

#!/bin/bash
i=0
while read line 
do
        arr[$i]="$line"
        i=$((i+1))
done < file.txt

答案 4 :(得分:1)

使用mapfile或读取-a

始终使用shellcheck检查您的代码。它通常会给你正确的答案。在这种情况下,SC2207涵盖了将空格分隔或换行符分隔的值读取到数组中的文件。

不要这样做

array=( $(mycommand) )

值由换行符分隔的文件

mapfile -t array < <(mycommand)

值以空格分隔的文件

IFS=" " read -r -a array <<< "$(mycommand)"

shellcheck页面将为您提供为什么这被认为是最佳实践的理由。

答案 5 :(得分:1)

This answer说使用

mapfile -t myArray < file.txt

如果您想在bash&lt;上使用mapfile,我为mapfile制作了shim 4.x无论出于何种原因。如果您使用的是bash&gt; = 4.x

,它会使用现有的mapfile命令

目前,只有选项-d-t有效。但这应该足以满足上述命令。我只在macOS上测试过。在macOS Sierra 10.12.6上,系统bash为3.2.57(1)-release。所以垫片可以派上用场。你也可以用自制软件更新你的bash,自己构建bash等等。

它使用this technique将变量设置为一个调用堆栈。