在 shell 中为 $* 的每个元素添加一个字符串

ere*_*non 5 shell brace-expansion

我正在寻找最简单的解决方案,将其$*作为输入,并扩展到以给定字符串为前缀和后缀的每个元素:

$*=foo bar baz
<solution(x,y)>=xfooy xbary xbazy
Run Code Online (Sandbox Code Playgroud)

我可以进行前置或附加,但不能同时进行:

echo ${*/#/x}
# prints xfoo xbar xbaz
Run Code Online (Sandbox Code Playgroud)
echo ${*/%/y}
# prints fooy bary bazy
Run Code Online (Sandbox Code Playgroud)

我无法结合这两种解决方案。该文档声称在 parameter=* 情况下扩展返回的值是一个列表,但我无法这样使用它。我想将生成的值数组作为单独的参数传递给另一个命令,因此简单地构建单个字符串是行不通的。

Sté*_*las 10

${var/pattern/replacement}是ksh93的参数扩展操作者,也由支撑zshmksh以及bash,虽与变化(mksh的目前还不能在阵列上操作)。

ksh93

在 中ksh93,您需要${var/*/x\0y}$varwith的扩展前加上x后缀y,并${array[@]/*/x\0y}为数组的每个元素都这样做。

因此,对于位置参数数组:

print -r -- "${@/*/x\0y}"
Run Code Online (Sandbox Code Playgroud)

(但是请注意,对于您的${*/#/x},当位置参数列表为空时会出现问题)。

zsh

zsh's等效的ksh93\0召回匹配字符串中的更换$MATCH,但前提是你使用(#m)的方式(请在您需要的extendedglob选项):

set -o extendedglob
print -r -- "${@/(#m)*/x${MATCH}y}"
Run Code Online (Sandbox Code Playgroud)

但是在 中zsh,您可以嵌套参数扩展,因此您还可以执行以下操作:

print -r -- ${${@/#/x}/%/y}
Run Code Online (Sandbox Code Playgroud)

尽管您可能更愿意使用为该数组的扩展$^array而打开的运算符rcexpandparam,但使其行为类似于大括号扩展:

print -r -- x$^@y
Run Code Online (Sandbox Code Playgroud)

或者你可以使用:

printf -v argv x%sy "$@"
Run Code Online (Sandbox Code Playgroud)

就地修改$@(又名$argvin zsh)(这里假设"$@"不是空列表)。

猛击

bashshell 中,您可能需要使用@L.ScottJohnson 所示的中间数组分两步完成,或者使用以下内容进行修改$@

set -- "${@/#/x}"
echo -E "${@/%/y}"
Run Code Online (Sandbox Code Playgroud)

(此处假设前缀(x在本例中)不以 开头-)。

POSIXly

您可以使用循环就地修改位置参数:

for i do
  set -- "$@" "x${i}y"
  shift
done
echo "$@"
Run Code Online (Sandbox Code Playgroud)

(但请注意,echo不能便携地用于显示可能包含反斜杠字符或以 开头的任意数据-

笔记

请注意,$*参数扩展的形式(仅用于引用)是用于连接位置参数($IFS默认为, SPC的第一个字符)的形式。您需要$@(再次引用)将所有位置参数扩展为分隔参数。未加引号,$*并且$@没有什么意义(除非zsh它们扩展到非空的位置参数),因为它们会受到 split+glob 的影响,并且行为因壳而异。


L. *_*son 4

#!/bin/bash
echo $*
FIELDS=("${@/#/x}")
FIELDS=("${FIELDS[@]/%/y}")
echo "${FIELDS[*]}"
Run Code Online (Sandbox Code Playgroud)

运行时:

$ t.sh foo bar baz
foo bar baz
xfooy xbary xbazy
Run Code Online (Sandbox Code Playgroud)

  • 请注意,“${var/pattern/replacement}”不是“sh”运算符。我建议不要为使用它的脚本提供“sh”扩展名。您还需要确保脚本由支持它的 shell(ksh93,它来自或 zsh/mksh/bash)解释,方法是使用相应的 `#! /path/to/shell -` she-bang. (3认同)
  • 需要强调的是,尽管许多人确实在非 POSIX shell 上使用“.sh”扩展名,但这在 bash 社区中是不受欢迎的。请参阅 freenode #bash IRC 机器人的相关事实的历史:http://wooledge.org/~greybot/meta/.sh;在这里引用其当前内容:“不要在脚本中使用扩展名。脚本定义了您可以运行的新命令,并且命令通常不会给出扩展名。您运行 `ls.elf` 吗?另外:bash 脚本*不是* sh 脚本(所以不要使用 .sh),如果脚本被用另一种语言重写,则扩展只会导致依赖性问题。” (2认同)