在 bash 中为 $@ 添加前缀和后缀

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/38558401/
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 14:55:55  来源:igfitidea点击:

Add prefix and suffix to $@ in bash

bash

提问by Richard

How to add suffix and prefix to $@?

如何添加后缀和前缀$@

If I do $PREFIX/$@/$SUFFIX, I get the prefix and the suffix only in the first parameter.

如果我这样做$PREFIX/$@/$SUFFIX,我只会在第一个参数中获得前缀和后缀。

回答by sjsam

I would use shell [ parameter expansion ]for this

我会用外壳 [参数扩展]

$ set -- one two three
$ echo "$@"
one two three
$ set -- "${@/#/pre}" && set -- "${@/%/post}"
$ echo "$@"
preonepost pretwopost prethreepost

Notes

笔记

  • The #matches the beginning
  • The %matches the end
  • Using double quotes around ${@}considers each element as a separate word. so replacement happens for every positional parameter
  • #开始处匹配
  • %结束比赛
  • 使用双引号${@}将每个元素视为一个单独的单词。所以每个位置参数都会发生替换

回答by John1024

Let's create a parameters for test purposes:

让我们为测试目的创建一个参数:

$ set -- one two three
$ echo "$@"
one two three

Now, let's use bash to add prefixes and suffixes:

现在,让我们使用 bash 添加前缀和后缀:

$ IFS=$'\n' a=($(printf "pre/%s/post\n" "$@"))
$ set -- "${a[@]}"
$ echo -- "$@"
pre/one/post pre/two/post pre/three/post

Limitations: (a) since this uses newline-separated strings, it won't work if your $@contains newlines itself. In that case, there may be another choice for IFSthat would suffice. (b) This is subject to globbing. If either of these is an issue, see the more general solution below.

限制:(a) 由于这使用换行符分隔的字符串,如果您$@包含换行符本身,它将不起作用。在这种情况下,可能有另一种选择IFS就足够了。(b) 这受制于通配符。如果其中任何一个是问题,请参阅下面更通用的解决方案。

On the other hand, if the positional parameters do not contain whitespace, then no change to IFSis needed.

另一方面,如果位置参数不包含空格,则不需要更改 to IFS

Also, if IFSis changed, then one may want to save IFSbeforehand and restore afterward.

此外,如果IFS更改了,则可能需要IFS事先保存并在之后恢复。

More general solution

更通用的解决方案

If we don't want to make any assumptions about whitespace, we can modify "$@" with a loop:

如果我们不想对空格做任何假设,我们可以用循环修改“$@”:

$ a=(); for p in "$@"; do a+=("pre/$p/post"); done
$ set -- "${a[@]}"
$ echo "$@"
pre/one/post pre/two/post pre/three/post

回答by mklement0

Note: This is essentially a slightly more detailed version of sjam's answer.

注意:这本质上是sjam's answer 的一个更详细的版本。

John1024's answeris helpful, but:

John1024 的回答很有帮助,但是:

  • requires a subshell(which involves a child process)
  • can result in unwanted globbingapplied to the array elements.
  • 需要一个子shell(它涉及一个子进程
  • 可能会导致不必要的通配符应用于数组元素。

Fortunately, Bash parameter expansioncan be applied to arraystoo, which avoids these issues:

幸运的是,Bash参数扩展也可以应用于数组,从而避免了这些问题:

set -- 'one' 'two' # sample input array, which will be reflected in $@

# Copy $@ to new array ${a[@]}, adding a prefix to each element.
# `/#` replaces the string that follows, up to the next `/`,
# at the *start* of each element.
# In the absence of a string, the replacement string following
# the second `/` is unconditionally placed *before* each element.
a=( "${@/#/PREFIX}" )

# Add a suffix to each element of the resulting array ${a[@]}.
# `/%` replaces the string that follows, up to the next `/`,
# at the *end* of each element.
# In the absence of a string, the replacement string following
# the second `/` is unconditionally placed *after* each element.
a=( "${a[@]/%/SUFFIX}" )

# Print the resulting array.
declare -p a

This yields:

这产生:

declare -a a='([0]="PREFIXoneSUFFIX" [1]="PREFIXtwoSUFFIX")'

Note that double-quoting the array referencesis crucial to protect their elements from potential word-splittingand globbing(filename expansion) - both of which are instances of shell expansions.

需要注意的是双引号的数组引用是至关重要的,以防止潜在的要素字分裂通配符(文件名扩展) -这两者都是实例shell扩展