bash数组的前缀和后缀元素

时间:2022-05-24 15:42:27

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...

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