Ответ 1
Ваша последняя петля может быть выполнена с помощью witespace-friendly:
EXPANDED=()
for E in "${ARRAY[@]}"; do
EXPANDED+=("prefix_${E}_suffix")
done
echo "${EXPANDED[@]}"
Я хочу предварительно и постфиксный массив в bash аналогично расширению скобки.
Скажем, у меня есть массив bash
ARRAY=( one two three )
Я хочу иметь возможность пред- и постфиксации, как и следующее расширение раскладки
echo prefix_{one,two,three}_suffix
Лучшее, что я смог найти, использует bash regex для добавления префикса или суффикса
echo ${ARRAY[@]/#/prefix_}
echo ${ARRAY[@]/%/_suffix}
но я не могу найти ничего о том, как сделать это одновременно. Потенциально я мог бы использовать регулярные выражения и делать что-то вроде
echo ${ARRAY[@]/.*/prefix_$1_suffix}
но похоже, что захваты поддерживаются в подстановке переменных bash regex. Я мог бы также хранить временную переменную массива, например
PRE=(${ARRAY[@]/#/prefix_})
echo ${PRE[@]/%/_suffix}
Это, наверное, лучшее, что я могу придумать, но все же кажется, что он подпадает. Конечной альтернативой является использование цикла for, близкого к
EXPANDED=""
for E in ${ARRAY[@]}; do
EXPANDED="prefix_${E}_suffix $EXPANDED"
done
echo $EXPANDED
но это супер уродливо. Я также не знаю, как бы я мог заставить его работать, если бы мне нужны пробелы где угодно, суффикс префикса или элементы массива.
Ваша последняя петля может быть выполнена с помощью witespace-friendly:
EXPANDED=()
for E in "${ARRAY[@]}"; do
EXPANDED+=("prefix_${E}_suffix")
done
echo "${EXPANDED[@]}"
Bash Расширение скобки не использует регулярные выражения. Используемый шаблон - это всего лишь некоторый shell glob, который вы можете найти в bash manual 3.5.8.1 Соответствие шаблону.
Ваше двухэтапное решение классно, но ему нужны некоторые цитаты для безопасности в виде пробелов:
ARR_PRE=("${ARRAY[@]/#/prefix_}")
echo "${ARR_PRE[@]/%/_suffix}"
Вы также можете сделать это каким-то злым образом:
eval "something $(printf 'pre_%q_suf ' "${ARRAY[@]}")"
Более приятный, но по существу тот же, что и решение циклы:
$ ARRAY=(A B C)
$ mapfile -t -d $'\0' EXPANDED < <(printf "prefix_%s_postfix\0" "${ARRAY[@]}")
$ echo "${EXPANDED[@]}"
prefix_A_postfix prefix_B_postfix prefix_C_postfix
mapfile
считывает строки в элементы массива. С помощью -d $'\0'
вместо этого он считывает нулевые -d строки, а -t
исключает разделитель из результата. См. help mapfile
.
Для массивов:
ARRAY=( one two three )
(IFS=,; eval echo prefix_\{"${ARRAY[*]}"\}_suffix)
Для строк:
STRING="one two three"
eval echo prefix_\{${STRING// /,}\}_suffix
eval
заставляет его аргументы оцениваться дважды, в обоих случаях первые результаты оценки в
echo prefix_{one,two,three}_suffix
и второй выполняет его. Для массива case subhell используется, чтобы избежать перезапуска IFS
Вы также можете сделать это в zsh:
echo ${${ARRAY[@]/#/prefix_}/%/_suffix}
У меня точно такой же вопрос, и я придумал следующее решение, используя механизм совпадения слов sed:
myarray=( one two three )
newarray=( $(echo ${myarray[*]}|sed "s/\(\b[^ ]\+\)/pre-\1-post/g") )
echo ${newarray[@]}
> pre-one-post pre-two-post pre-three-post
echo ${#newarray[@]}
> 3
Ожидание более элегантных решений...