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

Creating an array from a text file in Bash

一个脚本接受一个 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... 

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

使用mapfile命令:

mapfile -t myArray < file.txt

错误是使用 for -- 遍历文件的 的惯用方法是:

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

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

你也可以这样做:

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

注:

文件名扩展仍然存在。例如,如果有一行文字为 *,它将扩展到当前文件夹中的所有文件。所以只有当你的文件没有这种情况时才使用它。

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

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

mapfilereadarray(它们是同义词)在 Bash 版本 4 及更高版本中可用。如果你有旧版本的Bash,你可以使用循环将文件读入数组:

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

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

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

相关:

使用mapfile或读取-a

始终使用 shellcheck. It will often give you the correct answer. In this case SC2207 检查您的代码,包括将 space 分隔值或换行符分隔值读取到数组中的文件。

不要这样做

array=( $(mycommand) )

值由换行符分隔的文件

mapfile -t array < <(mycommand)

值由 spaces

分隔的文件
IFS=" " read -r -a array <<< "$(mycommand)"

shellcheck 页面会告诉您为什么这是最佳实践。

表示使用

mapfile -t myArray < file.txt

如果您想在 bash < 4.x 上使用 mapfile,我为 mapfile 创建了一个 shim。如果您使用 bash >= 4.x

,它会使用现有的 mapfile 命令

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

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