在 Bash 中从文本文件创建数组
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/30988586/
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
Creating an array from a text file in Bash
提问by user2856414
A script takes a URL, parses it for the required fields, and redirects its output to be saved in a file, file.txt. The output is saved on a new line each time a field has been found.
脚本获取一个 URL,将其解析为所需的字段,并将其输出重定向到一个文件file.txt 中。每次找到字段时,输出都会保存在新行上。
file.txt
文件.txt
A Cat
A Dog
A Mouse
etc...
I want to take file.txt
and create an array from it in a new script, where every line gets to be its own string variable in the array. So far I have tried:
我想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
When I run this script, whitespace results in words getting split and instead of getting
当我运行这个脚本时,空格会导致单词被拆分而不是
Desired output
期望输出
Element [0]: A Cat
Element [1]: A Dog
etc...
I end up getting this:
我最终得到这个:
Actual output
实际产量
Element [0]: A
Element [1]: Cat
Element [2]: A
Element [3]: Dog
etc...
How can I adjust the loop below such that the entire string on each line will correspond one-to-one with each variable in the array?
如何调整下面的循环,使每行的整个字符串与数组中的每个变量一一对应?
回答by glenn Hymanman
Use the mapfile
command:
使用mapfile
命令:
mapfile -t myArray < file.txt
The error is using for
-- the idiomatic way to loop over linesof a file is:
错误正在使用for
- 循环文件行的惯用方法是:
while IFS= read -r line; do echo ">>$line<<"; done < file.txt
See BashFAQ/005for more details.
有关更多详细信息,请参阅BashFAQ/005。
回答by codeforester
mapfile
and readarray
(which are synonymous) are available in Bash version 4 and above. If you have an older version of Bash, you can use a loop to read the file into an array:
mapfile
和readarray
(它们是同义词)在 Bash 版本 4 及更高版本中可用。如果您有旧版本的 Bash,您可以使用循环将文件读入数组:
arr=()
while IFS= read -r line; do
arr+=("$line")
done < file
In case the file has an incomplete (missing newline) last line, you could use this alternative:
如果文件的最后一行不完整(缺少换行符),您可以使用以下替代方法:
arr=()
while IFS= read -r line || [[ "$line" ]]; do
arr+=("$line")
done < file
Related:
有关的:
回答by Jahid
You can do this too:
你也可以这样做:
oldIFS="$IFS"
IFS=$'\n' arr=($(<file))
IFS="$oldIFS"
echo "${arr[1]}" # It will print `A Dog`.
Note:
笔记:
Filename expansion still occurs. For example, if there's a line with a literal *
it will expand to all the files in current folder. So use it only if your file is free of this kind of scenario.
文件名扩展仍然发生。例如,如果有一行带有文字*
,它将扩展到当前文件夹中的所有文件。因此,仅当您的文件没有这种情况时才使用它。
回答by Prateek Joshi
You can simply read each line from the file and assign it to an array.
您可以简单地从文件中读取每一行并将其分配给一个数组。
#!/bin/bash
i=0
while read line
do
arr[$i]="$line"
i=$((i+1))
done < file.txt
回答by Cameron Lowell Palmer
Use mapfile or read -a
使用 mapfile 或 read -a
Always check your code using shellcheck. It will often give you the correct answer. In this case SC2207covers reading a file that either has space separated or newline separated values into an array.
始终使用shellcheck检查您的代码。它通常会给你正确的答案。在这种情况下,SC2207涵盖将具有空格分隔或换行分隔值的文件读取到数组中。
Don't do this
不要这样做
array=( $(mycommand) )
Files with values separated by newlines
值由换行符分隔的文件
mapfile -t array < <(mycommand)
Files with values separated by spaces
值以空格分隔的文件
IFS=" " read -r -a array <<< "$(mycommand)"
The shellcheck page will give you the rationale why this is considered best practice.
shellcheck 页面将为您提供为什么这被认为是最佳实践的基本原理。
回答by dosentmatter
This answersays to use
这个答案说使用
mapfile -t myArray < file.txt
I made a shimfor mapfile
if you want to use mapfile
on bash < 4.x for whatever reason. It uses the existing mapfile
command if you are on bash >= 4.x
我做了一个垫片的mapfile
,如果你想使用mapfile
上的bash <4.x版无论出于何种原因。mapfile
如果您使用 bash >= 4.x,它会使用现有命令
Currently, only options -d
and -t
work. But that should be enough for that command above. I've only tested on macOS. On macOS Sierra 10.12.6, the system bash is 3.2.57(1)-release
. So the shim can come in handy. You can also just update your bash with homebrew, build bash yourself, etc.
目前,只有选择-d
和-t
工作。但这对于上面的命令应该足够了。我只在 macOS 上测试过。在 macOS Sierra 10.12.6 上,系统 bash 是3.2.57(1)-release
. 所以垫片可以派上用场。您也可以使用自制软件更新您的 bash,自己构建 bash 等。
It uses this techniqueto set variables up one call stack.
它使用这种技术在一个调用堆栈中设置变量。