以引号形式打印命令行参数



>$@ 当双引号("$@") 扩展到 "$1" "$2" "$3" ...

似乎没有简单的方法来打印"$@"内部内容的引用形式

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

我正在寻找的是,输出

'one two' three

使用 'set -x',是否回显了 "$@" 中引用的参数形式

$ set -x; echo "$@"; set +x
+ set -x
+ echo 'one two' three
one two three
+ set +x

用户定义的变量 $DOLLAR_AT 包含与 "$@"包含

$ DOLLAR_AT="'one two' three"

倾倒,$DOLLAR_AT内部的内容,使用"回显"按预期工作

$ echo $DOLLAR_AT
'one two' three

由于 shell 对包含特殊字符的参数进行某种自动引用

$ set -x; echo $DOLLAR_AT; set +x
+ echo ''''one' 'two'''' three
+ set +x

不清楚为什么

$ echo "$@"

不产生与 相同的输出

$ echo "$DOLLAR_AT"

当使用收到的"$@"从shell脚本启动命令时,有一个 在调用 命令。

打印从以下位置传递的命令行参数也有类似的需求 一个 bash 数组。

$ CMDARGS=("one two" "three")

计算双引号内的数组不会以引号形式打印数组元素

$ echo "${CMDARGS[@]}"
one two three

我还需要一种紧凑的方式来打印引用的 $CMDARGS[@] 中的内容 形式类似于此迭代的结果

$ for ARG in "${CMDARGS[@]}"; do echo '$ARG'; done
'one two'
'three'

1. 使用参数扩展

您可以尝试内联:

$ set -- 'foo bar' baz
$ echo ${@@Q}
'Foo bar' 'baz'
$ echo ${@@A}
set -- 'Foo bar' 'baz'
$ DOLLAR_AT="'one two' three"
$ echo ${DOLLAR_AT@Q}
''''one two''' three'
$ echo ${DOLLAR_AT@A}
DOLLAR_AT=''''one two''' three'

更多信息请参见 bash 手册页的"参数扩展"子部分下。

${parameter@operator}
Parameter transformation.  The expansion is either a transforma‐
tion  of  the  value of parameter or information about parameter
itself, depending on the value of operator.  Each operator is  a
single letter:
...
Q      The  expansion is a string that is the value of parameter
quoted in a format that can be reused as input.
...
A      The expansion is a string in the form  of  an  assignment
statement  or  declare  command  that, if evaluated, will
recreate parameter with its attributes and value.

要重复使用它:

$ myString1=${@@Q}
$ set -- something else
$ . <(echo "set -- $myString1")
$ echo ${@@A}
set -- 'Foo bar' 'baz'

1.1.$*$@的区别。

简单地$*用于生成字符串,其中$@可以根据上下文生成数组字符串

来自 bash 的手册页:

*      Expands to the positional parameters, starting from  one...
...   That  is, "$*" is equivalent to "$1c$2c...", where  c is
the first character of the value of the IFS variable...
@      Expands to the positional parameters,  starting  from  one...
...  That is, "$@" is equivalent to "$1" "$2" ... 

小演示:

$ paramExpDemo() {
local IFS=+ _arry
_arry="${@@Q}"         #  var="..." -> context string
declare -p _arry
_arry="${*@Q}"
declare -p _arry
_arry=("${@@Q}")       #  var=(...) -> context array
declare -p _arry
_arry=("${*@Q}")
declare -p _arry
}

然后

$ paramExpDemo  'foo bar' baz
declare -- _arry="'foo bar'+'baz'"
declare -- _arry="'foo bar'+'baz'"
declare -a _arry=([0]="'foo bar'" [1]="'baz'")
declare -a _arry=([0]="'foo bar'+'baz'")

在上下文string中,$@$*将给出相同的结果,但在上下文array中,当$@返回数组时,$*将返回一个字符串

$ set -- 'foo bar' baz
$ Array=("${@@Q}")
$ declare -p Array
declare -a Array=([0]="'foo bar'" [1]="'baz'")
$ echo "${Array[@]@Q}"
''''foo bar'''' ''''baz''''

2. 使用printf %q

正如Léa Gris正确评论的那样,您可以使用:

$ printf '%qn' "$@"
Foo bar
baz
$ printf -v myString2 "%q " "$@"
$ echo "${myString2% }"
Foo bar baz 

要重用它:

$ set -- something else
$ . <(echo "set -- $myString2")
$ echo ${@@A}
set -- 'Foo bar' 'baz'

注意:正如查尔斯·达菲(Charles Duffy)评论的那样,这并不完美!实际上,无法检索命令行中使用的语法。

$ printf "<%q>n" "$myString1" "${myString2% }"
<'Foo bar' 'baz'>
<Foo\ bar baz>

由于两个字符串都用于变量,因此它们并不相同,因此进一步的字符串操作可能会变得复杂......

最新更新