I want to pre- and postfix an array in bash similar to brace expansion.
我想在bash中预先修复一个数组,类似于大括号扩展。
Say I have a bash array
说我有一个bash数组
ARRAY=( one two three )
I want to be able to pre- and postfix it like the following brace expansion
我想能够像下面的大括号扩展一样预先修改它
echo prefix_{one,two,three}_suffix
The best I've been able to find uses bash regex to either add a prefix or a suffix
我能找到的最好用的是使用bash regex来添加前缀或后缀
echo ${ARRAY[@]/#/prefix_}
echo ${ARRAY[@]/%/_suffix}
but I can't find anything on how to do both at once. Potentially I could use regex captures and do something like
但我找不到任何关于如何同时做两件事的事情。我可能会使用正则表达式捕获并执行类似的操作
echo ${ARRAY[@]/.*/prefix_$1_suffix}
but it doesn't seem like captures are supported in bash variable regex substitution. I could also store a temporary array variable like
但似乎bash变量正则表达式替换中不支持捕获。我还可以存储一个临时数组变量
PRE=(${ARRAY[@]/#/prefix_})
echo ${PRE[@]/%/_suffix}
This is probably the best I can think of, but it still seems sub par. A final alternative is to use a for loop akin to
这可能是我能想到的最好的,但它似乎仍然低于标准杆。最后一种选择是使用类似于的for循环
EXPANDED=""
for E in ${ARRAY[@]}; do
EXPANDED="prefix_${E}_suffix $EXPANDED"
done
echo $EXPANDED
but that is super ugly. I also don't know how I would get it to work if I wanted spaces anywhere the prefix suffix or array elements.
但这太丑了。如果我想要前缀后缀或数组元素的空格,我也不知道如何让它工作。
5 个解决方案
#1
11
Your last loop could be done in a whitespace-friendly way with:
您的上一个循环可以通过以空格友好的方式完成:
EXPANDED=()
for E in "${ARRAY[@]}"; do
EXPANDED+=("prefix_${E}_suffix")
done
echo "${EXPANDED[@]}"
#2
7
Bash brace expansion don't use regexes. The pattern used is just some shell glob, which you can find in bash manual 3.5.8.1 Pattern Matching.
Bash大括号扩展不使用正则表达式。使用的模式只是一些shell glob,你可以在bash手册3.5.8.1模式匹配中找到它。
Your two-step solution is cool, but it needs some quotes for whitespace safety:
你的两步解决方案很酷,但它需要一些空白安全的引用:
ARR_PRE=("${ARRAY[@]/#/prefix_}")
echo "${ARR_PRE[@]/%/_suffix}"
You can also do it in some evil way:
你也可以用某种邪恶的方式做到这一点:
eval "something $(printf 'pre_%q_suf ' "${ARRAY[@]}")"
#3
2
Prettier but essentially the same as the loop solution:
更漂亮但与循环解决方案基本相同:
$ 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
reads rows into elements of an array. With -d $'\0'
it instead reads null-delimited strings and -t
omits the delimiter from the result. See help mapfile
.
mapfile将行读入数组的元素。使用-d $'\ 0'代替读取空分隔的字符串,-t省略结果中的分隔符。请参阅帮助mapfile。
#4
0
For arrays:
对于数组:
ARRAY=( one two three )
(IFS=,; eval echo prefix_\{"${ARRAY[*]}"\}_suffix)
For strings:
对于字符串:
STRING="one two three"
eval echo prefix_\{${STRING// /,}\}_suffix
eval
causes its arguments to be evaluated twice, in both cases first evaluation results in
eval导致其参数被评估两次,在这两种情况下,第一次评估结果都是
echo prefix_{one,two,three}_suffix
and second executes it. For array case subshell is used to avoid overwiting IFS
第二次执行它。对于数组情况,子shell用于避免覆盖IFS
You can also do this in zsh:
您也可以在zsh中执行此操作:
echo ${${ARRAY[@]/#/prefix_}/%/_suffix}
#5
0
I have exactly the same question, and I come up with the following solution using sed's word boundary match mechanism:
我有完全相同的问题,我使用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
Waiting for more elegant solutions...
等待更优雅的解决方案......
#1
11
Your last loop could be done in a whitespace-friendly way with:
您的上一个循环可以通过以空格友好的方式完成:
EXPANDED=()
for E in "${ARRAY[@]}"; do
EXPANDED+=("prefix_${E}_suffix")
done
echo "${EXPANDED[@]}"
#2
7
Bash brace expansion don't use regexes. The pattern used is just some shell glob, which you can find in bash manual 3.5.8.1 Pattern Matching.
Bash大括号扩展不使用正则表达式。使用的模式只是一些shell glob,你可以在bash手册3.5.8.1模式匹配中找到它。
Your two-step solution is cool, but it needs some quotes for whitespace safety:
你的两步解决方案很酷,但它需要一些空白安全的引用:
ARR_PRE=("${ARRAY[@]/#/prefix_}")
echo "${ARR_PRE[@]/%/_suffix}"
You can also do it in some evil way:
你也可以用某种邪恶的方式做到这一点:
eval "something $(printf 'pre_%q_suf ' "${ARRAY[@]}")"
#3
2
Prettier but essentially the same as the loop solution:
更漂亮但与循环解决方案基本相同:
$ 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
reads rows into elements of an array. With -d $'\0'
it instead reads null-delimited strings and -t
omits the delimiter from the result. See help mapfile
.
mapfile将行读入数组的元素。使用-d $'\ 0'代替读取空分隔的字符串,-t省略结果中的分隔符。请参阅帮助mapfile。
#4
0
For arrays:
对于数组:
ARRAY=( one two three )
(IFS=,; eval echo prefix_\{"${ARRAY[*]}"\}_suffix)
For strings:
对于字符串:
STRING="one two three"
eval echo prefix_\{${STRING// /,}\}_suffix
eval
causes its arguments to be evaluated twice, in both cases first evaluation results in
eval导致其参数被评估两次,在这两种情况下,第一次评估结果都是
echo prefix_{one,two,three}_suffix
and second executes it. For array case subshell is used to avoid overwiting IFS
第二次执行它。对于数组情况,子shell用于避免覆盖IFS
You can also do this in zsh:
您也可以在zsh中执行此操作:
echo ${${ARRAY[@]/#/prefix_}/%/_suffix}
#5
0
I have exactly the same question, and I come up with the following solution using sed's word boundary match mechanism:
我有完全相同的问题,我使用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
Waiting for more elegant solutions...
等待更优雅的解决方案......