您实际上并不需要那么多代码:
IFS=$'\n' sorted=($(sort <<<"${array[*]}"))
unset IFS
支持元素中的空格(只要不是换行符),and在 Bash 3.x 中工作。
e.g.:
$ array=("a c" b f "3 5")
$ IFS=$'\n' sorted=($(sort <<<"${array[*]}")); unset IFS
$ printf "[%s]\n" "${sorted[@]}"
[3 5]
[a c]
[b]
[f]
Note:@sorontar 有指出 https://stackoverflow.com/questions/7442417/how-to-sort-an-array-in-bash/11789688?noredirect=1#comment67720230_11789688如果元素包含通配符,则需要小心,例如*
or ?
:
Sorted=($(...)) 部分使用“split and glob”运算符。你应该关闭全局:set -f
or set -o noglob
or shopt -op noglob
或数组的一个元素,例如*
将扩展为文件列表。
发生了什么:
结果是按以下顺序发生的六件事达到顶峰:
IFS=$'\n'
"${array[*]}"
<<<
sort
sorted=($(...))
unset IFS
首先,IFS=$'\n'
这是我们操作的一个重要部分,它通过以下方式影响 2 和 5 的结果:
Given:
-
"${array[*]}"
扩展到由第一个字符分隔的每个元素IFS
-
sorted=()
通过分割每个字符来创建元素IFS
IFS=$'\n'
安排事情 https://unix.stackexchange.com/questions/184863/what-is-the-meaning-of-ifs-n-in-bash-scripting这样元素就可以使用扩展一条新线作为分隔符,然后以每行成为一个元素的方式创建。 (即在新行上拆分。)
用新行分隔很重要,因为这就是sort
操作(每行排序)。分割依据only新行并不那么重要,但需要保留包含空格或制表符的元素。
默认值为IFS
is a space, a tab, 其次是一条新线,并且不适合我们的操作。
接下来,sort <<<"${array[*]}"
part
<<<
,称为这里是字符串 https://unix.stackexchange.com/questions/80362/what-does-mean, 取展开式"${array[*]}"
,如上所述,并将其输入到标准输入中sort
.
以我们的例子来说,sort
被输入以下字符串:
a c
b
f
3 5
Since sort
sorts,它产生:
3 5
a c
b
f
接下来,sorted=($(...))
part
The $(...)
部分,称为命令替换 http://www.tldp.org/LDP/abs/html/commandsub.html,导致其内容(sort <<<"${array[*]}
)作为普通命令运行,同时获取结果标准输出就像字面意思一样$(...)
was.
在我们的示例中,这会产生类似于简单编写的内容:
sorted=(3 5
a c
b
f
)
sorted
然后变成一个数组,通过在每个新行上分割这个文字来创建。
最后,unset IFS
这将重置值IFS
为默认值,这只是一个很好的做法。
这是为了确保我们不会对任何依赖的东西造成麻烦IFS
稍后在我们的脚本中。 (否则我们需要记住我们已经改变了一些东西——这对于复杂的脚本来说可能不切实际。)