为什么与以破折号开头的CLI参数一起使用时,代字号(〜)不会展开?


9

我花了几个小时试图运行VNC服务器(x0vncserver),并且客户端拒绝连接并发出奇怪的消息,

No password configured for VNC Auth

服务器还会打印此错误

 SVncAuth:    opening password file '~/.vnc/passwd' failed

好的,我浪费了很多时间,直到意识到波浪号既没有被shell扩展,也没有被x0vncserver扩展。然后我进行了这些测试

$ echo --PasswordFile=~/.vnc/passwd
--PasswordFile=~/.vnc/passwd

$ echo PasswordFile=~/.vnc/passwd
PasswordFile=/home/tichomir/.vnc/passwd

这是为什么?如果参数以短划线开头,为什么shell拒绝扩展代字号?我认为只要不加引号,波浪号就会一直扩展,但是显然还有另外一条规则在起作用吗?



Answers:


13

这是bash其手册中描述的shell 的独特之处:

当满足变量分配条件的单词(如上文“参数”中所述)作为简单命令的参数出现时,Bash还会对它们进行波浪号扩展。在posix模式下,Bash不会执行上述操作,除了上面列出的声明命令。

这意味着bash 扩展PasswordFile=~/.vnc/passwd字符串中的波浪号,因为它的参数echo看起来像变量赋值。

该字符串--PasswordFile=~/.vnc/passwd看起来像变量分配,因为该字符串--PasswordFile不是有效的变量名称。

请注意,bash在POSIX模式下运行时不这样做,那其他炮弹一样zshksh或者yash默认不这样做(zsh有一个magicequalsubst要加引号等号后进行了波浪线扩展选项(=)虽然)。

如果要确保将当前用户的主目录路径作为命令参数的一部分正确扩展,请使用该$HOME值代替波浪号:

echo --PasswordFile="$HOME/.vnc/passwd"

的“上面列出声明命令”中提到的手册中内置的命令aliasdeclaretypesetexportreadonly,和local


1
+1 | 我不会想到的。
LinuxSecurityFreak

虽然注意:bash --posix -c '"export" a=~; printf "%s\n" "$a"'输出~
—StéphaneChazelas,

2
请注意,~被扩展alias a=~将是POSIX一致性错误(并且没有用)。但这就是ksh88的工作方式(在ksh93中进行了更改),并且可能就是bash,zsh和pdksh也这样做的原因。为什么yash针对POSIX规范编写的代码却没有做到这一点。
斯特凡Chazelas

这是正确的答案,但是正确的方法是只将option参数作为一个单独的参数提供,而不是使用=一个参数与option合并。然后,波浪号扩展在一个单词的开头,问题就没有意义了。
JdeBP '19

1
@JdeBP,因为它发生在的情况下x0vncserverx0vncserver --PasswordFile file不工作,你需要--PasswordFile=file
—StéphaneChazelas,
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.