如何在BASH中从数组中提取特定元素?

48

以下是我创建Bash数组的方法:

while read line
do
   myarr[$index]=$line
   index=$(($index+1))
done < lines.txt

文件"lines.txt"包含以下字符串

hello big world!
how are you
where am I

创建${myarr[@]}之后,我可以轻松访问数组中的每个元素(行),发出

echo ${myarr[2]}

但如果我只想提取world!怎么办? 是否可以从myarr的第0个元素中提取world!? 最重要的是,是否可以从myarr元素中提取任何最后一个单词?

我知道在Python中,您可以执行myarr [0] [3]就可以做到这一点,那在Bash中呢?


数组元素是字符串 - 行的副本。它们本身不是单词数组或任何其他东西。如果您愿意,可以拆分数组元素,但没有将数组元素自动拆分为单词的功能。 - Jonathan Leffler
4个回答

47

这是许多方式之一

set ${myarr[2]}
echo $3

2
建议使用以下命令:set -- ${mayarr[2]},这样如果数组元素的值为-x -e,你的shell就不会开始跟踪并在出现错误时退出。 - Jonathan Leffler
12
a=( ${myarr[2]} ); echo ${a[3]}的作用相同,不会覆盖您可能用于其他用途的shell /函数位置参数。 - chepner
1
@chepner,我建议使用a=(“${myarr [2]}”); - Artfaith

30

您可以使用变量扩展中的修改器从字符串(即数组元素)中提取单词:#(删除前缀),##(删除前缀,贪婪匹配),%(删除后缀)和%%(删除后缀,贪婪匹配)。

$ myarr=('hello big world!' 'how are you' 'where am I')
$ echo "${myarr[0]}"      # Entire first element of the array
hello big world!
$ echo "${myarr[0]##* }"  # To get the last word, remove prefix through the last space
world!
$ echo "${myarr[0]%% *}"  # To get the first word, remove suffix starting with the first space
hello
$ tmp="${myarr[0]#* }"    # The second word is harder; first remove through the first space...
$ echo "${tmp%% *}"       # ...then get the first word of what remains
big
$ tmp="${myarr[0]#* * }"  # The third word (which might not be the last)? remove through the second space...
$ echo "${tmp%% *}"       # ...then the first word again
world!

正如您所看到的,这里可以变得相当复杂,但是在某些时候,@chepner的建议将其转换为数组会更容易。此外,我建议用于提取第二个等单词的公式有点脆弱:如果您使用我的公式提取仅具有两个单词的字符串的第三个单词,则第一个修剪将失败,并且它将打印第一个(!)单词而不是空白。此外,如果您连续使用两个空格,它将将其视为空长度单词,并在其两侧加上一个空格...

顺便说一句,在构建数组时,我认为使用+=(新元素)要比明确跟踪数组索引要清晰一些:

myarr=()
while read line, do
    myarr+=("$line")
done < lines.txt

8
类似于 stephen-penny 的回答,但不会覆盖 shell/function 的位置参数。
a=(${myarr[2]})
echo ${a[3]}

8
从数组中使用索引打印特定元素:
echo ${my_array[2]}

要打印数组中的所有元素,可以执行以下操作:

for i in "${my_array[@]}"
do
    echo $i
done

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接