bash数组的前缀和后缀元素

时间:2013-12-04 04:05:00

标签: regex arrays bash

我想在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变量正则表达式替换中不支持捕获。我还可以存储一个临时数组变量,如

PRE=(${ARRAY[@]/#/prefix_})
echo ${PRE[@]/%/_suffix}

这可能是我能想到的最好的,但它似乎仍然低于标准杆。最后一种方法是使用类似于

的for循环
EXPANDED=""
for E in ${ARRAY[@]}; do
    EXPANDED="prefix_${E}_suffix $EXPANDED"
done
echo $EXPANDED

但这太丑了。如果我想要前缀后缀或数组元素的空格,我也不知道如何让它工作。

5 个答案:

答案 0 :(得分:13)

Bash大括号扩展不使用正则表达式。使用的模式只是一些shell glob,您可以在bash手册3.5.8.1 Pattern Matching中找到它。

你的两步解决方案很酷,但需要一些空白安全引用:

ARR_PRE=("${ARRAY[@]/#/prefix_}")
echo "${ARR_PRE[@]/%/_suffix}"

你也可以用邪恶的方式做到这一点:

eval "something $(printf 'pre_%q_suf ' "${ARRAY[@]}")"

答案 1 :(得分:12)

您的上一个循环可以通过以下方式以空格友好的方式完成:

EXPANDED=()
for E in "${ARRAY[@]}"; do
    EXPANDED+=("prefix_${E}_suffix")
done
echo "${EXPANDED[@]}"

答案 2 :(得分:2)

更漂亮但与循环解决方案基本相同:

$ 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',它会读取空分隔的字符串,而-t会忽略结果中的分隔符。请参阅help mapfile

答案 3 :(得分:1)

对于数组:

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

并且第二次执行它。 对于数组情况,子shell用于避免覆盖IFS

您也可以在zsh中执行此操作:

echo ${${ARRAY[@]/#/prefix_}/%/_suffix}

答案 4 :(得分:0)

我有完全相同的问题,我使用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

等待更优雅的解决方案...