Bash $(printf“%q'”${@:1})是否等于“${*}”?

Bash $(printf“%q'”${@:1})是否等于“${*}”?,bash,shell,arguments,parameter-passing,posix,Bash,Shell,Arguments,Parameter Passing,Posix,$printf'%q'${@:1}是否等于${*} 如果它们是,那么就执行$printf'%q'${@:2}注意,使用纯bash$* 相关问题: 不,它不是等价的,因为单词是分开的。例如,以下代码: check_args() { echo "\$#=$#" printf "%s\n" "$@"; } # setting arguments set -- "space notspace" "newline"$'\n'"newline" echo '1: ----------------

$printf'%q'${@:1}是否等于${*}

如果它们是,那么就执行$printf'%q'${@:2}注意,使用纯bash$*

相关问题:


不,它不是等价的,因为单词是分开的。例如,以下代码:

check_args() {
  echo "\$#=$#"
  printf "%s\n" "$@";
}

# setting arguments
set -- "space notspace" "newline"$'\n'"newline"
echo '1: ---------------- "$*"'
check_args "$*"

echo '2: ---------------- $(printf '\''%q '\'' "${@:1}")'
check_args $(printf '%q ' "${@:1}")

echo '3: ---------------- "$(printf '\''%q '\'' "${@:1}")"'
check_args "$(printf '%q ' "${@:1}")"

echo '4: ---------------- IFS=@ and "$*"'
( IFS=@; check_args "$*"; )

echo "5: ---------------- duplicating quoted"
check_args "$(printf '%s'"${IFS:0:1}" "${@:1}" | sed 's/'"${IFS:0:1}"'$//')"

echo "6: ---------------- duplicating quoted IFS=@"
( IFS=@; check_args "$(printf '%s'"${IFS:0:1}" "${@:1}" | sed 's/'"${IFS:0:1}"'$//')"; )

echo "7: ---------------- duplicating eval unquoted"
eval check_args $(printf '%q"'"${IFS:0:1}"'"' "${@:1}" | sed 's/'"${IFS:0:1}"'$//')

echo "8: ---------------- duplicating eval unquoted IFS=@"
( eval check_args $(IFS=@ ; printf '%q"'"${IFS:0:1}"'"' "${@:1}" | sed 's/"'"${IFS:0:1}"'"$//'); )
将输出:

1: ---------------- "$*"
$#=1
space notspace newline
newline
2: ---------------- $(printf '%q ' "${@:1}")
$#=3
space\
notspace
$'newline\nnewline'
3: ---------------- "$(printf '%q ' "${@:1}")"
$#=1
space\ notspace $'newline\nnewline'
4: ---------------- IFS=@ and "$*"
$#=1
space notspace@newline
newline
5: ---------------- duplicating quoted
$#=1
space notspace newline
newline
6: ---------------- duplicating quoted IFS=@
$#=1
space notspace@newline
newline
7: ---------------- duplicating eval unquoted
$#=1
space notspace newline
newline
8: ---------------- duplicating eval unquoted IFS=@
$#=1
space notspace@newline
newline
经过测试

$*输出由IFS确定的参数。因此,如测试4所示,如果delimeter没有取消设置或设置为空格,那么在本例中,@的IFS将对$*的输出进行delimeter

另外,当IFS未设置或设置为空格时,$*的输出不包括终止空格,而printf“%q”将始终在字符串的末尾打印一个尾随空格

$printf'%q'${@:1}的输出仍在空间上拆分。因此,测试用例2接收3个参数,因为空格notspace字符串由空格分隔并拆分为两个参数。如果将printf封装在内部,则不会有任何帮助-printf用例如换行符代替\n字符

案例5、6、7、8是我尝试使用printf复制$*的行为。在我使用eval的案例7和案例8中可以看到,在案例5和案例6中,我引用了命令替换。案例5和6以及案例7和8的输出应分别与案例1和案例4的输出相匹配

为了复制$*的行为,需要特别注意IFS正确地测量字符串。我使用sed的/'${IFS:0:1}'$/'从printf输出中删除尾随的IFS分隔符。第5和第6个案例是未报价的$printf。。。尝试,6使用IFS=@显示分离的作品。第7和第8种情况使用eval对IFS进行特殊处理,因为IFS字符本身需要用引号括起来,所以shell不会在其上再次拆分,这就是为什么printf“%q”${IFS:0:1}”

执行$printf“%q”${@:2}注意,对于纯bash$*,不能像以前那样使用2而不是1

您可能只需要在替换$shift中转移参数;printf%s\n$*,但如上所示,它们无论如何都不是等价的。

使用answer作为基础,我构建了这个新的测试代码,用于演示,还包括:

!/bin/bash 检查参数{ 回音\$=$ 本地计数器=0 对于var in$@ 做 计数器=$计数器+1; printf$counter.'$var'; 完成 printf\\n\\n } 设置参数 set-space-notspace-lastargument;计数器=1 echo$计数器“:-----------$*”;计数器=$counter+1 检查参数$* echo$计数器“:-----------$*”;计数器=$counter+1 检查参数$* echo$计数器“:-----------$@”;计数器=$counter+1 检查参数$@ echo$计数器“:-----------$@”;计数器=$counter+1 检查参数$@ echo$counter':----------$printf'\%q'\${@:1}';计数器=$counter+1 检查参数$printf'%q'${@:1} echo$counter':----------$printf'\%q'\${@:1}';计数器=$counter+1 检查参数$printf'%q'${@:1} echo$counter':-----------IFS=@和$*';计数器=$counter+1 如果=@;勾选_args$*; echo$计数器------重复报价;计数器=$counter+1 检查_args$printf“%s”${IFS:0:1}${@:1}| sed的/'${IFS:0:1}'$/' echo$计数器:---复制引用的IFS=@;计数器=$counter+1 如果=@;检查_args$printf“%s”${IFS:0:1}${@:1}| sed's/'${IFS:0:1}$/'; echo$计数器:---复制未报价的评估;计数器=$counter+1 评估检查参数$printf'%q'${IFS:0:1}'${@:1}| sed's/'${IFS:0:1}'$/' echo$计数器:---复制评估未引用的IFS=@;计数器=$counter+1 评估检查参数$IFS=@;printf'%q'${IFS:0:1}'${@:1}| sed's/'${IFS:0:1}'$/'; ->


为什么不试试看呢?使用更常用的${*}编写$*会产生一个字符串。POSIX没有为printf命令或printf函数指定%q转换规范。您必须参考您的系统的文档才能知道这将要做什么。
GNU bash, version 4.4.12(1)-release (x86_64-pc-linux-gnu)
1: ---------------- "$*"
$#=1
1. 'space notspace lastargument',

2: ---------------- $*
$#=3
1. 'space', 2. 'notspace', 3. 'lastargument',

3: ---------------- "$@"
$#=2
1. 'space notspace', 2. 'lastargument',

4: ---------------- $@
$#=3
1. 'space', 2. 'notspace', 3. 'lastargument',

5: ---------------- $(printf '%q ' "${@:1}")
$#=3
1. 'space', 2. 'notspace', 3. 'lastargument',

6: ---------------- "$(printf '%q ' "${@:1}")"
$#=1
1. 'space\ notspace lastargument ',

7: ---------------- IFS=@ and "$*"
$#=1
1. 'space notspace@lastargument',

8: ---------------- duplicating quoted
$#=1
1. 'space notspace lastargument',

9: ---------------- duplicating quoted IFS=@
$#=1
1. 'space notspace@lastargument',

10: ---------------- duplicating eval unquoted
$#=1
1. 'space notspace lastargument ',

11: ---------------- duplicating eval unquoted IFS=@
$#=1
1. 'space notspace@lastargument',