如何在bash中连接数组?

Posted

技术标签:

【中文标题】如何在bash中连接数组?【英文标题】:How to concatenate arrays in bash? 【发布时间】:2015-09-17 13:56:05 【问题描述】:

我是 Bash 的新手。我有一个从标准输入获取输入的数组。我必须将自己连接两次。说,我在数组中有以下元素:

Namibia
Nauru
Nepal
Netherlands
NewZealand
Nicaragua
Niger
Nigeria
NorthKorea
Norway

现在,输出应该是:

Namibia Nauru Nepal Netherlands NewZealand Nicaragua Niger Nigeria NorthKorea Norway Namibia Nauru Nepal Netherlands NewZealand Nicaragua Niger Nigeria NorthKorea Norway

我的代码是:

countries=()
while read -r country; do
    countries+=( "$country" )
done
countries=countries+countries+countries # this is the wrong way, i want to know the right way to do it
echo "$countries[@]"

请注意,我可以像下面的代码一样打印三次,但这不是我的座右铭。我必须将它们连接到数组中。

countries=()
while read -r country; do
    countries+=( "$country" )
done
echo "$countries[@] $countries[@] $countries[@]"

【问题讨论】:

您已经在自己的代码中添加了数组... @HuStmpHrrr,将单个项目附加到一个数组(通过附加一个单值数组),是的,但我可以理解为什么有人不理解他们已经使用的语法。 但我不知道,如何添加自己。谢谢。 @HuStmpHrrr 【参考方案1】:

首先,将您的列表读入一个数组,每行一个条目:

readarray -t countries

...或者,使用旧版本的 bash:

# same, but compatible with bash 3.x; || is to avoid non-zero exit status.
IFS=$'\n' read -r -d '' countries || (( $#countries[@] ))

其次,要复制条目,要么将数组扩展到自身三倍:

countries=( "$countries[@]" "$countries[@]" "$countries[@]" )

...或使用现代语法执行追加:

countries+=( "$countries[@]" "$countries[@]" )

【讨论】:

当像上一个例子那样连接数组时,为什么不使用"$countries[*]"(而不是像打印时那样使用"$countries[@]")? @jww,使用 "$countries[*]" 将仅添加 一个 数组元素,该数组元素包含一个字符串,整个国家列表连接在一起,而不是每个国家一个元素。 @jww, ...而相比之下,不带引号的$countries[*] 将更改名称中带有空格的国家/地区——比如New Guinea——将每个单词分隔到自己的列表中元素(为NewGuinea 中的每一个添加一个单独的数组元素)。【参考方案2】:

在 ubuntu 14.04 上,以下将连接三个元素(元素计数将给出:3),每个元素是一个数组 countries

countries=( "$countries[@]" "$countries[@]" "$countries[@]" )

而下面的代码会将所有元素连接到一个数组中:

countries=( $countries[*] $countries[*] $countries[*] )

这个计数将是 30(考虑到原始帖子中指定的国家/地区)。

【讨论】:

这是错误的。 countries=( "$countries[@]" "$countries[@]" "$countries[@]" ) 将原始数组扩展 3 次,每个原始数组元素创建一个元素,每 3 次。 countries=( $countries[*] $countries[*] $countries[*] ),相比之下,string-splits 和 glob-expands 原始数组。假设你有countries=( "New Guinea" "New Zealand" "North Korea" )result=( "$countries[@]" "$countries[@]" "$countries[@]" ) 扩展到九个项目。 相比之下,result=( $countries[*] $countries[*] $countries[*] ) 扩展为 18 项,因为每个 New 都成为自己的数组元素。 (如果它拆分成的任何一个单词都是可以匹配本地磁盘上文件的glob,那就更复杂了!) ...查看此代码在在线解释器中运行,其输出位于ideone.com/Bj9LLM【参考方案3】:

简单地写这个:

countries=$(cat)
countries+=( "$countries[@]" "$countries[@]" )
echo $countries[@]

第一行是输入数组,第二行是连接,最后是打印数组。

【讨论】:

countries=$(cat) 将从标准输入获取的单个字符串分配给数组的第一个元素;个别元素没有分解到个别国家。 (使用declare -p countries显示数组的定义,行为会很明显)。 ...也就是说,当你这样做时,你的数组不是countries=( A B C A B C A B C )而是countries=( "A B C" "A B C" "A B C" );根本看不出这是一个问题,因为使用中的echo 命令引用不充分,因此拆分了它的参数。使用printf '%q\n' "$countries[@]",每个集合将位于不同的行,这同样会使问题可见(而如果正确填充数组,每个 country 将位于不同的行)。跨度>

以上是关于如何在bash中连接数组?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Bash 中连接字符串变量

如何在 Bash 中加入数组的元素?

如何在只有 1 个连接的 bash 循环中运行多个 sqlplus 查询

在bash中,如何将N个参数连接在一起作为空格分隔的字符串

分布式监控系统Zabbix3.2监控数据库的连接数

两个数组如何对应相加js