bash特殊参数的问题

bash特殊参数的问题,bash,Bash,有人能解释一下为什么这个输出会分裂成一个新行吗 $cat./test-args.sh #!/usr/bin/env bash 而[$#-gt 0]];做 打印文件“%b%b%b%b\n”$0“$1”$\ 转移 完成 $./test-args.sh a b c d e ./test-args.sh a 5 a b、c、d、e /test-args.sh b 4 b c d e ./test-args.sh c 3 c d e ./test-args.sh d 2 d E ./test-args.s

有人能解释一下为什么这个输出会分裂成一个新行吗

$cat./test-args.sh
#!/usr/bin/env bash
而[$#-gt 0]];做
打印文件“%b%b%b%b\n”$0“$1”$\
转移
完成
$./test-args.sh a b c d e
./test-args.sh a 5 a
b、c、d、e
/test-args.sh b 4 b
c d e
./test-args.sh c 3 c
d e
./test-args.sh d 2 d
E
./test-args.sh e 1 e
将特殊参数指定给变量会按预期工作:

$cat./test-args.sh
#!/usr/bin/env bash
而[$#-gt 0]];做
a=$0
b=1美元
c=$#
d=$@
打印文件“%b%b%b%b\n”$a“$b”$c“$d”
转移
完成
$./test-args.sh a b c d e
./test-args.sh a 5 a b c d e
./test-args.sh b 4 b c d e
./test-args.sh c 3 c d e
./test-args.sh d 2 d e
./test-args.sh e 1 e

printf
提供的属性多于其格式使用的属性时,它将重新使用其格式。在您的例子中,
“$@”
被扩展到包含在双引号中的所有参数,(
“a”“b”“c”“d”“e”
在第一个例子中)和
printf
接收8个参数,它使用其格式字符串的两次出现来显示这些参数,从而给出意外的输出


为了避免这种行为,您需要使用将扩展为单个参数的
“$*”
,在第一种情况下使用
“a b c d e”

printf
提供的属性多于其格式使用的属性时,它将重新使用其格式。在您的例子中,
“$@”
被扩展到包含在双引号中的所有参数,(
“a”“b”“c”“d”“e”
在第一个例子中)和
printf
接收8个参数,它使用其格式字符串的两次出现来显示这些参数,从而给出意外的输出


为了避免这种行为,您需要使用将扩展为单个参数的
“$*”
,在第一种情况下使用
“a b c d e”

printf
接收到额外参数时,它会在额外的字上重复格式字符串。例如:

$ printf '[%s]\n' a b c
[a]
[b]
[c]
您的
printf
格式字符串需要四个参数,但
“$@”
会扩展为多个单词。它在格式字符串上运行了两次,这就是为什么
\n
显示在“中间”。如果将格式字符串更改为
'\n'
,则会变得清晰:

$ ./test-args.sh a b c d e
<./test-args.sh a 5 a>
<b c d e>
<./test-args.sh b 4 b>
<c d e >
<./test-args.sh c 3 c>
<d e  >
<./test-args.sh d 2 d>
<e   >
<./test-args.sh e 1 e>

printf
收到额外的参数时,它会在额外的单词上重复格式字符串。例如:

$ printf '[%s]\n' a b c
[a]
[b]
[c]
您的
printf
格式字符串需要四个参数,但
“$@”
会扩展为多个单词。它在格式字符串上运行了两次,这就是为什么
\n
显示在“中间”。如果将格式字符串更改为
'\n'
,则会变得清晰:

$ ./test-args.sh a b c d e
<./test-args.sh a 5 a>
<b c d e>
<./test-args.sh b 4 b>
<c d e >
<./test-args.sh c 3 c>
<d e  >
<./test-args.sh d 2 d>
<e   >
<./test-args.sh e 1 e>

我们的想法是,printf循环遍历参数。所以在第一个循环中

printf '%b %b %b %b\n' "$0" "$1" "$#" "$@"
扩展到

printf '%b %b %b %b\n' ./test-args.sh a 5 a b c d e
printf接受前4个参数
/test-args.sh a 5 a
,并使用
%b%b%b\n
打印它们。然后它需要另外4个(或更少)参数
b c d e
,并再次使用
%b%b%b\n
打印它们。基本上
printf“%b%b%b%b\n”。/test-args.sh a 5 a b c d e

printf '%b %b %b %b\n' ./test-args.sh a 5 a b
printf '%b %b %b %b\n' b c d e
因此它可以打印多行。
这将满足您的要求:

while (($#)); do
    printf '%s ' "$0" "$1" "$#" "$@"
    printf '\n'
    shift
done
或者可能:

while (($#)); do
    printf '%s %s %s %s\n' "$0" "$1" "$#" "$*"
    shift
done

我们的想法是,printf循环遍历参数。所以在第一个循环中

printf '%b %b %b %b\n' "$0" "$1" "$#" "$@"
扩展到

printf '%b %b %b %b\n' ./test-args.sh a 5 a b c d e
printf接受前4个参数
/test-args.sh a 5 a
,并使用
%b%b%b\n
打印它们。然后它需要另外4个(或更少)参数
b c d e
,并再次使用
%b%b%b\n
打印它们。基本上
printf“%b%b%b%b\n”。/test-args.sh a 5 a b c d e

printf '%b %b %b %b\n' ./test-args.sh a 5 a b
printf '%b %b %b %b\n' b c d e
因此它可以打印多行。
这将满足您的要求:

while (($#)); do
    printf '%s ' "$0" "$1" "$#" "$@"
    printf '\n'
    shift
done
或者可能:

while (($#)); do
    printf '%s %s %s %s\n' "$0" "$1" "$#" "$*"
    shift
done