arrays - 如何在 Bash 中对数组进行排序

标签 arrays bash shell sorting

我在 Bash 中有一个数组,例如:

array=(a c b f 3 5)

我需要对数组进行排序。不仅仅是以排序的方式显示内容,而是获得一个包含排序元素的新数组。新的排序数组可以是全新的,也可以是旧的。

最佳答案

你真的不需要那么多代码:

IFS=$'\n' sorted=($(sort <<<"${array[*]}"))
unset IFS

支持元素中的空格(只要它不是换行符),并且在 Bash 3.x 中工作。

例如:

$ array=("a c" b f "3 5")
$ IFS=$'\n' sorted=($(sort <<<"${array[*]}")); unset IFS
$ printf "[%s]\n" "${sorted[@]}"
[3 5]
[a c]
[b]
[f]

注意: @sorontar 有 pointed out如果元素包含通配符,例如 *,则需要小心或 ? :

The sorted=($(...)) part is using the "split and glob" operator. You should turn glob off: set -f or set -o noglob or shopt -op noglob or an element of the array like * will be expanded to a list of files.

发生了什么:

结果是按以下顺序发生的六件事的高潮:

  1. IFS=$'\n'
  2. "${array[*]}"
  3. <<<
  4. sort
  5. sorted=($(...))
  6. unset IFS

首先,IFS=$'\n'

这是我们操作的一个重要部分,它以下列方式影响 2 和 5 的结果:

给定:

  • "${array[*]}"扩展到由 IFS 的第一个字符分隔的每个元素
  • sorted=()通过拆分 IFS 的每个字符来创建元素

IFS=$'\n' sets things up以便使用新行作为分隔符扩展元素,然后以每行成为一个元素的方式创建元素。 (即在新行上拆分。)

用新行分隔很重要,因为这就是 sort 的方式操作(每行排序)。 换行并不重要,但需要保留包含空格或制表符的元素。

默认值IFS一个空格一个制表符,后面是一个新行,不适合我们的操作。

接下来,sort <<<"${array[*]}"部分

<<< , 称为 here strings , 展开 "${array[*]}" , 如上所述,并将其输入到 sort 的标准输入中.

在我们的例子中,sort被提供以下字符串:

a c
b
f
3 5

sort 排序,它产生:

3 5
a c
b
f

接下来,sorted=($(...))部分

$(...)部分,称为 command substitution , 导致其内容 ( sort <<<"${array[*]} ) 作为普通命令运行,同时将生成的标准输出 作为字面量,无论$(...) 在哪里。是。

在我们的示例中,这会产生类似于简单写入的内容:

sorted=(3 5
a c
b
f
)

sorted然后变成一个数组,它是通过在每一行上拆分这个文字创建的。

最后,unset IFS

这会重置 IFS 的值为默认值,这只是一种很好的做法。

这是为了确保我们不会对任何依赖 IFS 的东西造成麻烦稍后在我们的脚本中。 (否则我们需要记住我们已经改变了一些东西——这对于复杂的脚本来说可能是不切实际的。)

关于arrays - 如何在 Bash 中对数组进行排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7442417/

相关文章:

php - 在php中检索数据库记录集到数组中

bash - Ansible 命令,Shell 模块不执行脚本

linux - 如何包含具有相对路径的 bash 脚本?

100 次迭代的 Bash shell 脚本和记录时间

mysql - 停止来自 mysql 终端的警告

bash - shell 脚本 : unexpected token ´if"

sql - 如何将变量从shell脚本传递到sql文件

java - 如何将字符串中的 11 个数字选择到数组中?

JavaScript 循环太慢

ruby - 替换索引与给定索引不匹配的数组中的元素