Никогда не использовал bash, но разве для ассоциативного массива вообще имеет смысл "порядок элементов"? А легкий гуглеж выдает: "порядок, в котором значения кодируются в ассоциативном массиве, не обязательно должен совпадать с порядком, в котором они отображаются"
> но разве для ассоциативного массива вообще имеет смысл "порядок элементов"?
А вы попробуйте выбрать последовательно все элементы такого массива. Окажется, что какой-то порядок должен быть. Кроме того, в баше массив - это в общем-то просто текстовая строка, в которой какие-то значащие наборы символов разделены пробельными символами. А такая строка - это всегда определённая последовательность. В баше есть только одномерные массивы и часто для всяких трюков используются не значения, а именно ключи, и их порядок может иметь значение.
И снова вылазит, так сказать, отказ от категориального знания :-/ Порядок (читай: отношение порядка) "правой стороны" хэш-отображения -- дело интуитивно непредсказуемое.
# В новом массиве в качестве ключей и значений # используем значения из исходного массива for i in "${one[@]}" do two["$i"]="$i" done
# Выводим список ключей echo "${!two[@]}"
# Выводим содержимое нового массива echo "${two[@]}"
#------------------------------------ # # THE SOLUTION: # for k in $(for k in "${!two[@]}"; do echo $k; done | sort); do echo "two[$k] = ${two[$k]}" done---------8><------------
Re: Есть такое делоalex_dragonAugust 14 2022, 18:21:22 UTC
Дык с сортом каждый дурак сумеет. :-D) А sort у нас вроде к built-in не относится, следовательно вызов в цикле внешней команды - это такое, не кошерное, только в крайнем случае. Я думал, может слона не приметил и есть какой-то стандартный и вменяемый способ без колдовства.
Re: Есть такое делоrexy_craxyAugust 14 2022, 18:31:40 UTC
В bash такого способа нет, увы. Там, строго говоря, нельзя делать априорные предположения о порядке ключей в assoc-массивах. Такова плата за "вкрячивание" -- классическая Bourne shell про assoc-arrays ничего не знала.
ЗЫ Для продвинутого скриптинга я бы рекомендовал Tcl (LISP-вдохновенный шелл) или newLISP (это вообще мега-жемчужина, катастрофически недооцениваемая б***-массами, самый "человечный" и быстрейший в мире "честный" интерпретатор ЛИСПа).
Re: Есть такое делоalex_dragonAugust 14 2022, 19:02:50 UTC
Как-нибудь надо tcl поинтересоваться. Но тут по ходу интересный вопрос возникает: какова вероятность что он по умолчанию из коробки в наугад взятом дистре устанавливается?
Тут ведь от назначения и возможного применения много зависит. Одно дело когда можешь тянуть какие хочешь зависимости, другое - когда дай бог чтобы хотя бы coreutils стояли.
Дык, это прямое следствие из самой сути хеширования (а большинство современных реализаций ассоков делается через хеш). Прозрачная для юзера сортировка ключей/по-ключам в некоторых языках (или библиотеках, например, STL) -- "сахар" от разработчиков.
Comments 25
( ... )
Reply
А легкий гуглеж выдает: "порядок, в котором значения кодируются в ассоциативном массиве, не обязательно должен совпадать с порядком, в котором они отображаются"
Reply
А вы попробуйте выбрать последовательно все элементы такого массива. Окажется, что какой-то порядок должен быть. Кроме того, в баше массив - это в общем-то просто текстовая строка, в которой какие-то значащие наборы символов разделены пробельными символами. А такая строка - это всегда определённая последовательность. В баше есть только одномерные массивы и часто для всяких трюков используются не значения, а именно ключи, и их порядок может иметь значение.
Reply
Порядок (читай: отношение порядка) "правой стороны" хэш-отображения -- дело интуитивно непредсказуемое.
Reply
Reply
Однако:
---------8><------------
#!/bin/bash
# Создаём обычный индексированный массив
one=("a" "b" "c" "d")
# Объявляем ассоциативный массив
declare -A two
# В новом массиве в качестве ключей и значений
# используем значения из исходного массива
for i in "${one[@]}"
do
two["$i"]="$i"
done
# Выводим список ключей
echo "${!two[@]}"
# Выводим содержимое нового массива
echo "${two[@]}"
#------------------------------------
#
# THE SOLUTION:
#
for k in $(for k in "${!two[@]}"; do echo $k; done | sort); do
echo "two[$k] = ${two[$k]}"
done---------8><------------
Ну, и не забываем, что sort умеет много гитик ;-)
Reply
Reply
В bash такого способа нет, увы. Там, строго говоря, нельзя делать априорные предположения о порядке ключей в assoc-массивах. Такова плата за "вкрячивание" -- классическая Bourne shell про assoc-arrays ничего не знала.
ЗЫ Для продвинутого скриптинга я бы рекомендовал Tcl (LISP-вдохновенный шелл) или newLISP (это вообще мега-жемчужина, катастрофически недооцениваемая б***-массами, самый "человечный" и быстрейший в мире "честный" интерпретатор ЛИСПа).
Reply
Тут ведь от назначения и возможного применения много зависит. Одно дело когда можешь тянуть какие хочешь зависимости, другое - когда дай бог чтобы хотя бы coreutils стояли.
Reply
Reply
Reply
Leave a comment