如何在 Bash 中对数组进行排序 [英] How to sort an array in Bash

查看:36
本文介绍了如何在 Bash 中对数组进行排序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have an array in Bash, for example:

array=(a c b f 3 5)

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

I need to sort the array. Not just displaying the content in a sorted way, but to get a new array with the sorted elements. The new sorted array can be a completely new one or the old one.

推荐答案

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

You don't really need all that much code:

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

支持元素中的空格(只要它不是换行符),并且适用于 Bash 3.x.

Supports whitespace in elements (as long as it's not a newline), and works in 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 有 指出 如果元素包含通配符,例如*?,则需要注意:

Note: @sorontar has pointed out that care is required if elements contain wildcards such as * or ?:

sorted=($(...)) 部分使用了split and glob"运算符.您应该关闭 glob:set -fset -o noglobshopt -op noglob 或像 这样的数组元素* 将扩展为文件列表.

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.

发生了什么:

结果是按此顺序发生的六件事达到了顶峰:

What's happening:

The result is a culmination six things that happen in this order:

  1. IFS=$'\n'
  2. "${array[*]}"
  3. <<<<
  4. 排序
  5. sorted=($(...))
  6. 取消设置 IFS

首先,IFS=$'\n'

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

First, the IFS=$'\n'

This is an important part of our operation that affects the outcome of 2 and 5 in the following way:

给定:

  • "${array[*]}" 扩展到由 IFS
  • 的第一个字符分隔的每个元素
  • sorted=() 通过拆分 IFS
  • 的每个字符来创建元素
  • "${array[*]}" expands to every element delimited by the first character of IFS
  • sorted=() creates elements by splitting on every character of IFS

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

IFS=$'\n' sets things up so that elements are expanded using a new line as the delimiter, and then later created in a way that each line becomes an element. (i.e. Splitting on a new line.)

以新行分隔很重要,因为这就是 sort 的操作方式(按行排序).拆分一个新行并不重要,但需要保留包含空格或制表符的元素.

Delimiting by a new line is important because that's how sort operates (sorting per line). Splitting by only a new line is not-as-important, but is needed preserve elements that contain spaces or tabs.

IFS 的默认值是一个空格一个制表符,然后是一个新行,以及将不适合我们的操作.

The default value of IFS is a space, a tab, followed by a new line, and would be unfit for our operation.

<<<,称为这里的字符串,取"${array[*]}" 的扩展,如上所述,并将其输入到sort 的标准输入中.

<<<, called here strings, takes the expansion of "${array[*]}", as explained above, and feeds it into the standard input of sort.

在我们的示例中,sort 被输入以下字符串:

With our example, sort is fed this following string:

a c
b
f
3 5

由于sort sorts,它产生:

3 5
a c
b
f

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

$(...) 部分,称为 命令替换,使其内容(sort <<<<<"${array[*]})作为普通命令运行,而将结果标准输出作为文字,到达$(...)所在的位置.

Next, the sorted=($(...)) part

The $(...) part, called command substitution, causes its content (sort <<<"${array[*]}) to run as a normal command, while taking the resulting standard output as the literal that goes where ever $(...) was.

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

In our example, this produces something similar to simply writing:

sorted=(3 5
a c
b
f
)

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

sorted then becomes an array that's created by splitting this literal on every new line.

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

This resets the value of IFS to the default value, and is just good practice.

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

It's to ensure we don't cause trouble with anything that relies on IFS later in our script. (Otherwise we'd need to remember that we've switched things around--something that might be impractical for complex scripts.)

这篇关于如何在 Bash 中对数组进行排序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆