Вам не нужно столько кода:
IFS=$'\n' sorted=($(sort <<<"${array[*]}"))
unset IFS
Поддерживает пробелы в элементах (если это не перевод строки), и работает в Bash 3.x.
например:
$ array=("a c" b f "3 5")
$ IFS=$'\n' sorted=($(sort <<<"${array[*]}"))
$ printf "[%s]\n" "${sorted[@]}"
[3 5]
[a c]
[b]
[f]
Примечание: @sorontar имеет указал , что необходимо соблюдать осторожность, если элементы содержат символы подстановки, такие как *
или ?
:
Часть sorted = ($ (...)) использует оператор «split and glob».Вы должны отключить glob: set -f
или set -o noglob
или shopt -op noglob
, или элемент массива, такой как *
, будет расширен до списка файлов.
Что происходит:
Результатом является кульминация шести вещей, которые происходят в следующем порядке:
IFS=$'\n'
"${array[*]}"
<<<
sort
sorted=($(...))
unset IFS
Во-первых, IFS=$'\n'
Это важная частьнашей операции, которая влияет на результат 2 и 5 следующим образом:
Дано:
"${array[*]}"
распространяется на каждый элемент, ограниченный первым символом IFS
sorted=()
создает элементы путем разбиения на каждый символ IFS
IFS=$'\n'
устанавливает элементы так, чтобы элементы расширялись с использованием aновая строка в качестве разделителя, а затем создается таким образом, что каждая строка становится элементом.(т. е. разделение на новую строку.)
Важное значение имеет разделение новой строкой, поскольку именно так работает sort
(сортировка по строке).Разделение только на * - новая строка не так важна, но необходима для сохранения элементов, содержащих пробелы или табуляции.
Значение по умолчанию IFS
равно пробел , табуляция , за которой следует новая строка , и она будет непригодна для нашей операции.
Далее, sort <<<"${array[*]}"
part
<<<
, называемый здесь строки , принимает расширение "${array[*]}"
, как описано выше, и подает его на стандартный ввод sort
.
В нашем примере sort
подается следующая строка:
a c
b
f
3 5
Так как sort
сортирует , он выдает:
3 5
a c
b
f
Далее,sorted=($(...))
part
Часть $(...)
, называемая подстановка команд , заставляет ее содержимое (sort <<<"${array[*]}
) запускаться как обычная команда, принимаярезультирующий стандартный вывод в качестве литерала, который идет туда, где когда-либо был $(...)
.
В нашем примере это производит нечто похожее на простое написание:
sorted=(3 5
a c
b
f
)
sorted
затемстановится массивом, который создается путем разделения этого литерала на каждую новую строку.
Наконец, unset IFS
Это сбрасывает значение IFS
к значению по умолчанию, и это просто хорошая практика.
Это сделано для того, чтобы мы не создавали проблем ни с чем, что опирается на IFS
позже в нашем скрипте.(В противном случае нам нужно помнить, что мы все изменили - что может быть непрактично для сложных сценариев.)