$(printf '%q ' "${@:1}") 等同于“${*}”吗?
Is $(printf '%q ' "${@:1}") equivalent to "${*}"?
$(printf '%q ' "${@:1}")
是否等同于"${*}"
?
如果是,那么,使用纯 bash $*
?
不可能执行 $(printf '%q ' "${@:2}")
(注意 2 而不是之前的 1)
相关问题:
- POSIX sh equivalent for Bash’s printf %q
- Bash printf %q invalid directive
不,这不等价,因为单词被拆分了。前任。以下代码:
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
在 repl.
上测试
"$*"
输出由 IFS 分隔的参数。因此,如测试 4
所示,如果分隔符未设置或设置为 space,则 $*
的输出将由 IFS 分隔,在此示例中为 @
。
此外,当 IFS 未设置或设置为 space 时,$*
的输出不包含终止 space,而 printf '%q '
将始终打印尾随 space 在字符串的末尾。
$(printf '%q ' "${@:1}")
的输出仍然在 space 上拆分。所以测试用例 2
接收到 3 个参数,因为 space notspace
字符串被 space 分隔并拆分为两个参数。当将 printf
包含在 "
中时,将无济于事 - printf
替代 ex。 \n
个字符换行。
案例 5
、6
、7
、8
是我尝试使用 printf 复制 "$*"
的行为。可以看出用例7
和8
我用了eval
,用例5
和6
我引用了命令替换。案例(5
和6
)和(7
和8
)的输出应分别与案例1
和4
的输出相匹配。
为了复制 "$*"
的行为,需要特别注意 IFS
以正确分隔字符串。我使用 sed 's/'"${IFS:0:1}"'$//'
从 printf
输出中删除尾随的 IFS 分隔符。 5
和 6
案例是未引用的 $(printf ...)
尝试,6
使用 IFS=@
来显示分离作品。 7
和 8
案例使用对 IFS
进行特殊处理的 eval,因为 IFS
字符本身需要用引号引起来,因此 shell 将不再分裂,这就是为什么 printf '%q"'"${IFS:0:1}"'"'
.
doing $(printf '%q ' "${@:2}") (note the 2 instead of 1 as before) is not possible with pure bash $*?
您可能只是将参数转移到替换 $(shift; printf "%s\n" "$*")
中,但如上所示,它们无论如何都不等价。
使用@Kamil Cuk answer as base, I built this new testing code for illustration, also available on repl:
#!/bin/bash
check_args() {
echo "$#=$#"
local counter=0
for var in "$@"
do
counter=$((counter+1));
printf "$counter. '$var', ";
done
printf "\n\n"
}
# setting arguments
set -- "space notspace" "lastargument"; counter=1
echo $counter': ---------------- "$*"'; counter=$((counter+1))
check_args "$*"
echo $counter': ---------------- $*'; counter=$((counter+1))
check_args $*
echo $counter': ---------------- "$@"'; counter=$((counter+1))
check_args "$@"
echo $counter': ---------------- $@'; counter=$((counter+1))
check_args $@
echo $counter': ---------------- $(printf '\''%q '\'' "${@:1}")'; counter=$((counter+1))
check_args $(printf '%q ' "${@:1}")
echo $counter': ---------------- "$(printf '\''%q '\'' "${@:1}")"'; counter=$((counter+1))
check_args "$(printf '%q ' "${@:1}")"
echo $counter': ---------------- IFS=@ and "$*"'; counter=$((counter+1))
( IFS=@; check_args "$*"; )
echo "$counter: ---------------- duplicating quoted"; counter=$((counter+1))
check_args "$(printf '%s'"${IFS:0:1}" "${@:1}" | sed 's/'"${IFS:0:1}"'$//')"
echo "$counter: ---------------- duplicating quoted IFS=@"; counter=$((counter+1))
( IFS=@; check_args "$(printf '%s'"${IFS:0:1}" "${@:1}" | sed 's/'"${IFS:0:1}"'$//')"; )
echo "$counter: ---------------- duplicating eval unquoted"; counter=$((counter+1))
eval check_args $(printf '%q"'"${IFS:0:1}"'"' "${@:1}" | sed 's/'"${IFS:0:1}"'$//')
echo "$counter: ---------------- duplicating eval unquoted IFS=@"; counter=$((counter+1))
( eval check_args $(IFS=@ ; printf '%q"'"${IFS:0:1}"'"' "${@:1}" | sed 's/"'"${IFS:0:1}"'"$//'); )
-->
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',
$(printf '%q ' "${@:1}")
是否等同于"${*}"
?
如果是,那么,使用纯 bash $*
?
$(printf '%q ' "${@:2}")
(注意 2 而不是之前的 1)
相关问题:
- POSIX sh equivalent for Bash’s printf %q
- Bash printf %q invalid directive
不,这不等价,因为单词被拆分了。前任。以下代码:
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
在 repl.
上测试"$*"
输出由 IFS 分隔的参数。因此,如测试 4
所示,如果分隔符未设置或设置为 space,则 $*
的输出将由 IFS 分隔,在此示例中为 @
。
此外,当 IFS 未设置或设置为 space 时,$*
的输出不包含终止 space,而 printf '%q '
将始终打印尾随 space 在字符串的末尾。
$(printf '%q ' "${@:1}")
的输出仍然在 space 上拆分。所以测试用例 2
接收到 3 个参数,因为 space notspace
字符串被 space 分隔并拆分为两个参数。当将 printf
包含在 "
中时,将无济于事 - printf
替代 ex。 \n
个字符换行。
案例 5
、6
、7
、8
是我尝试使用 printf 复制 "$*"
的行为。可以看出用例7
和8
我用了eval
,用例5
和6
我引用了命令替换。案例(5
和6
)和(7
和8
)的输出应分别与案例1
和4
的输出相匹配。
为了复制 "$*"
的行为,需要特别注意 IFS
以正确分隔字符串。我使用 sed 's/'"${IFS:0:1}"'$//'
从 printf
输出中删除尾随的 IFS 分隔符。 5
和 6
案例是未引用的 $(printf ...)
尝试,6
使用 IFS=@
来显示分离作品。 7
和 8
案例使用对 IFS
进行特殊处理的 eval,因为 IFS
字符本身需要用引号引起来,因此 shell 将不再分裂,这就是为什么 printf '%q"'"${IFS:0:1}"'"'
.
doing $(printf '%q ' "${@:2}") (note the 2 instead of 1 as before) is not possible with pure bash $*?
您可能只是将参数转移到替换 $(shift; printf "%s\n" "$*")
中,但如上所示,它们无论如何都不等价。
使用@Kamil Cuk answer as base, I built this new testing code for illustration, also available on repl:
#!/bin/bash
check_args() {
echo "$#=$#"
local counter=0
for var in "$@"
do
counter=$((counter+1));
printf "$counter. '$var', ";
done
printf "\n\n"
}
# setting arguments
set -- "space notspace" "lastargument"; counter=1
echo $counter': ---------------- "$*"'; counter=$((counter+1))
check_args "$*"
echo $counter': ---------------- $*'; counter=$((counter+1))
check_args $*
echo $counter': ---------------- "$@"'; counter=$((counter+1))
check_args "$@"
echo $counter': ---------------- $@'; counter=$((counter+1))
check_args $@
echo $counter': ---------------- $(printf '\''%q '\'' "${@:1}")'; counter=$((counter+1))
check_args $(printf '%q ' "${@:1}")
echo $counter': ---------------- "$(printf '\''%q '\'' "${@:1}")"'; counter=$((counter+1))
check_args "$(printf '%q ' "${@:1}")"
echo $counter': ---------------- IFS=@ and "$*"'; counter=$((counter+1))
( IFS=@; check_args "$*"; )
echo "$counter: ---------------- duplicating quoted"; counter=$((counter+1))
check_args "$(printf '%s'"${IFS:0:1}" "${@:1}" | sed 's/'"${IFS:0:1}"'$//')"
echo "$counter: ---------------- duplicating quoted IFS=@"; counter=$((counter+1))
( IFS=@; check_args "$(printf '%s'"${IFS:0:1}" "${@:1}" | sed 's/'"${IFS:0:1}"'$//')"; )
echo "$counter: ---------------- duplicating eval unquoted"; counter=$((counter+1))
eval check_args $(printf '%q"'"${IFS:0:1}"'"' "${@:1}" | sed 's/'"${IFS:0:1}"'$//')
echo "$counter: ---------------- duplicating eval unquoted IFS=@"; counter=$((counter+1))
( eval check_args $(IFS=@ ; printf '%q"'"${IFS:0:1}"'"' "${@:1}" | sed 's/"'"${IFS:0:1}"'"$//'); )
-->
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',