我在 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
orset -o noglob
orshopt -op noglob
or an element of the array like*
will be expanded to a list of files.
发生了什么:
结果是按以下顺序发生的六件事的高潮:
-
IFS=$'\n'
-
"${array[*]}"
-
<<<
-
sort
-
sorted=($(...))
-
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/