我想在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
但这太丑了。如果我想要前缀后缀或数组元素的空格,我也不知道如何让它工作。
答案 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
等待更优雅的解决方案...