通过参数扩展(即不使用 printf)追加(更改)每个数组元素?

通过参数扩展(即不使用 printf)追加(更改)每个数组元素?

让下面的脚本来说明我的困境..

#!/bin/zsh

STUFF=( moose-hoof ovary clydsedale )

echo ${MINE=$(printf "MY-%s " $STUFF)}
echo ${MINE_EXP=${STUFF/^/MY-}}

MY-驼鹿蹄 MY-卵巢 MY-clydsedale

驼鹿蹄子房 clydsedale

允许在数组的每个元素上进行字符串连接的正确扩展标志是什么?

答案1

使用$^array

它将数组转换为数组的大括号扩展。至于在什么时候a=(foo bar baz)$^a会有点像{foo,bar,baz}

$ a=(foo bar baz)
$ echo prefix${^a}suffix
prefixfoosuffix prefixbarsuffix prefixbazsuffix

为了复用数组:

$ a=(1 2 3) b=(a b c)
$ echo $^a$^b
1a 1b 1c 2a 2b 2c 3a 3b 3c

当然,如果前缀或后缀包含 shell 特殊字符(例如;分隔命令或分隔单词的空格,或$"'&*[?~...),则必须将它们括起来:

echo 'p r e f i x '$^a' s u f f i x'

csh's 相同(以及 bash、ksh、zsh):

echo 'p r e f i x '{foo,bar,baz}' s u f f i x'

$^a本身不得被引用,"foo${^a}bar"将扩展为单词。您希望被引用的一种情况是当您想保留空元素时,$^array与 for 相同。$array然后,您需要引用数组扩展并使用标志(@)"${array[@]}"语法(让人想起 Bourne shell 的"$@"):

$ array=(x '')
$ printf '<%s>\n' $array         # empties removed
<x>
$ printf '<%s>\n' "$array"       # array elts joined with spaces
<x >
$ printf '<%s>\n' "${(@)array}"  # empties preserved
<x>
<>
$ printf '<%s>\n' "$array[@]"    # empties preserved
<x>
<>
$ printf '<%s>\n' $^array$^array # empty removed
<xx>
<x>
<x>
$ printf '<%s>\n' "$^array$^array" # concatenation of joined arrays
<x x >
$ printf '<%s>\n' "$^array[@]$^array[@]" # multiplexing with empties preserved
<xx>
<x>
<x>
<>

答案2

虽然这是一个相当古老的线程,但我想添加我最近的发现来做同样的事情参数扩展代替:

${name/pattern/repl}

...

该模式可以以“#”开头,在这种情况下,该模式必须在字符串的开头匹配,或者以“%”开头,在这种情况下,它必须在字符串的末尾匹配,或 '#%' 在这种情况下,模式必须匹配整个字符串。 repl 可以是空字符串,在这种情况下,最后的“/”也可以省略。在其他情况下,要引用最后的“/”,其前面应有一个反斜杠;如果“/”出现在替换参数内,则不需要这样做。另请注意,如果“#”、“%”和“#%”出现在替换参数内,即使在开头,它们也不会处于活动状态。

这允许在字符串的开头/结尾匹配模式,并且没有限制只能使用模式,#或者%它可以用于前缀和后缀数组:

$ array=(foo bar baz)
$ echo ${array/#/prefix_}
prefix_foo prefix_bar prefix_baz
$ echo ${array/%/_suffix}
foo_suffix bar_suffix baz_suffix

虽然对于字符串来说肯定没有那么方便,因为它们可以更容易地操作,但它仍然是可行的:

$ string="bar"
$ echo ${string/#/foo_}
foo_bar
$ echo ${string/%/_baz}
bar_baz

相关内容