bash 数组的前缀和后缀元素

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20366609/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 08:51:19  来源:igfitidea点击:

Prefix and postfix elements of a bash array

regexarraysbash

提问by Erik

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

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

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.

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

回答by Arthur2e5

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 Pattern Matching 中找到它。

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[@]}")"

回答by John Kugelman

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[@]}"

回答by Niklas Holm

Prettier but essentially the same as the loop solution:

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

$ ARRAY=(A B C)
$ mapfile -t -d $'
ARRAY=( one two three )
(IFS=,; eval echo prefix_\{"${ARRAY[*]}"\}_suffix)
' EXPANDED < <(printf "prefix_%s_postfix
STRING="one two three"
eval echo prefix_\{${STRING// /,}\}_suffix
" "${ARRAY[@]}") $ echo "${EXPANDED[@]}" prefix_A_postfix prefix_B_postfix prefix_C_postfix

mapfilereads rows into elements of an array. With -d $'\0'it instead reads null-delimited strings and -tomits the delimiter from the result. See help mapfile.

mapfile将行读入数组元素。-d $'\0'而是使用它读取空分隔的字符串并-t从结果中省略分隔符。见help mapfile

回答by Ryba

For arrays:

对于数组:

echo prefix_{one,two,three}_suffix

For strings:

对于字符串:

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

evalcauses its arguments to be evaluated twice, in both cases first evaluation results in

eval导致其参数被评估两次,在这两种情况下,第一次评估都会导致

myarray=( one two three )
newarray=( $(echo ${myarray[*]}|sed "s/\(\b[^ ]\+\)/pre--post/g") )
echo ${newarray[@]}
> pre-one-post pre-two-post pre-three-post
echo ${#newarray[@]}
> 3

and second executes it. For array case subshell is used to avoid overwiting IFS

然后第二个执行它。对于数组 case 子shell 用于避免覆盖 IFS

You can also do this in zsh:

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

##代码##

回答by bruin

I have exactly the same question, and I come up with the following solution using sed's word boundary match mechanism:

我有完全相同的问题,我使用 sed 的字边界匹配机制提出了以下解决方案:

##代码##

Waiting for more elegant solutions...

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