为什么 --text="$@" 只传递第一个单词?

Omi*_*mid 10 shell bash quoting

当我使用一些参数运行以下脚本时arg1 arg2 arg3

#!/bin/bash
zenity --entry --text="$@"
Run Code Online (Sandbox Code Playgroud)

zenity 使用以下文本创建一个条目对话框:“arg1”而我期望“arg1 arg2 arg3”

如果我使用类似以下脚本的变量,它会显示条目文本的所有参数。

#!/bin/bash
text="$@"
zenity --entry --text="$text"
Run Code Online (Sandbox Code Playgroud)

这些脚本之间有什么区别?为什么第一个只替换$@第一个参数?

jw0*_*013 16

$@扩展为单独的单词(而$*扩展为单个单词),如bash手册中所述。因此,当你写

zenity --text="$@"
Run Code Online (Sandbox Code Playgroud)

它扩展到

zenity --text="$1" "$2" "$3"
Run Code Online (Sandbox Code Playgroud)

但是,shell 变量赋值不会进行分词。请注意,bash手册中变量赋值的扩展列表中省略了字段/单词拆分。此行为与POSIX 规范一致。所以,当你写

text="$@"
Run Code Online (Sandbox Code Playgroud)

该变量text将所有位置参数作为一个单词获取,等效于如果您编写了text="$*". 事实上,这就是变量赋值中通常不需要双引号的原因。两个都

text=$@
Run Code Online (Sandbox Code Playgroud)

text=$*
Run Code Online (Sandbox Code Playgroud)

是完全安全的。

所以,

text=$@
zenity --option="$text"
Run Code Online (Sandbox Code Playgroud)

扩展"$text"为一个单词,这就是为什么它有效。请注意, the--option="$@"只是 command 的一个普通参数zenity,而不是 shell 变量赋值,这就是分词发生在这里而不是 in 的原因text=$@


man*_*ork 7

$@ 在单独的单词中扩展每个参数,成为

zenity --entry --text="arg1" "arg2" "arg3" # syntactically wrong for zenity
Run Code Online (Sandbox Code Playgroud)

使用$*代替将其扩展为一个单词

zenity --entry --text="$*"
Run Code Online (Sandbox Code Playgroud)

这将成为

zenity --entry --text="arg1 arg2 arg3" # syntactically correct for zenity
Run Code Online (Sandbox Code Playgroud)