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
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:
我想取文件。在新脚本中创建一个数组,其中的每一行都是数组中自己的字符串变量。到目前为止,我尝试过:
#!/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?
如何调整下面的循环,使每行上的整个字符串与数组中的每个变量一一对应?
6 个解决方案
#1
57
Use the mapfile
command:
使用mapfile命令:
mapfile -t myArray < file.txt
The error is using for
-- the idiomatic way to loop over lines of a file is:
这个错误是用于——循环文件行数的惯用方法是:
while IFS= read -r line; do echo ">>$line<<"; done < file.txt
See BashFAQ/005 for more details.
详情请参阅BashFAQ/005。
#2
4
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.
文件名扩张仍然发生。例如,如果有一行文字*,它将扩展到当前文件夹中的所有文件。因此,只有在您的文件没有这种情况时才使用它。
#3
3
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:
在Bash version 4和以上版本中,可以使用mapfile和readarray(它们是同义的)。如果您有一个旧版本的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:
相关:
- Need alternative to readarray/mapfile for script on older system
- 对于旧系统上的脚本,需要选择readarray/mapfile
#4
2
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
#5
0
Use mapfile or read -a
Always check your code using shellcheck. It will often give you the correct answer. In this case SC2207 covers 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页面将告诉您为什么这被认为是最佳实践。
#6
0
This answer says to use
这个答案是用
mapfile -t myArray < file.txt
I made a shim for 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
如果您想在bash < 4上使用mapfile,我为mapfile做了一个shim。x不管出于什么原因。如果您在bash >= 4.x上,它将使用现有的mapfile命令
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。这样垫片就能派上用场了。您还可以使用homebrew更新您的bash,自己构建bash,等等。
It uses this technique to set variables up one call stack.
它使用这种技术来设置一个调用堆栈中的变量。
#1
57
Use the mapfile
command:
使用mapfile命令:
mapfile -t myArray < file.txt
The error is using for
-- the idiomatic way to loop over lines of a file is:
这个错误是用于——循环文件行数的惯用方法是:
while IFS= read -r line; do echo ">>$line<<"; done < file.txt
See BashFAQ/005 for more details.
详情请参阅BashFAQ/005。
#2
4
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.
文件名扩张仍然发生。例如,如果有一行文字*,它将扩展到当前文件夹中的所有文件。因此,只有在您的文件没有这种情况时才使用它。
#3
3
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:
在Bash version 4和以上版本中,可以使用mapfile和readarray(它们是同义的)。如果您有一个旧版本的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:
相关:
- Need alternative to readarray/mapfile for script on older system
- 对于旧系统上的脚本,需要选择readarray/mapfile
#4
2
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
#5
0
Use mapfile or read -a
Always check your code using shellcheck. It will often give you the correct answer. In this case SC2207 covers 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页面将告诉您为什么这被认为是最佳实践。
#6
0
This answer says to use
这个答案是用
mapfile -t myArray < file.txt
I made a shim for 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
如果您想在bash < 4上使用mapfile,我为mapfile做了一个shim。x不管出于什么原因。如果您在bash >= 4.x上,它将使用现有的mapfile命令
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。这样垫片就能派上用场了。您还可以使用homebrew更新您的bash,自己构建bash,等等。
It uses this technique to set variables up one call stack.
它使用这种技术来设置一个调用堆栈中的变量。