我可以写
VAR=$VAR1
VAR=${VAR1}
VAR="$VAR1"
VAR="${VAR1}"
Run Code Online (Sandbox Code Playgroud)
最终结果对我来说似乎都差不多。我为什么要写一个或另一个?这些中的任何一个都不是便携式/ POSIX 吗?
过去的旧建议是对任何涉及 a 的表达式加双引号$VARIABLE
,至少在希望 shell 将其解释为单个项目的情况下,否则,内容中的任何空格$VARIABLE
都会脱离 shell。
但是,我知道在较新版本的 shell 中,不再总是需要双引号(至少出于上述目的)。例如,在bash
:
% FOO='bar baz'
% [ $FOO = 'bar baz' ] && echo OK
bash: [: too many arguments
% [[ $FOO = 'bar baz' ]] && echo OK
OK
% touch 'bar baz'
% ls $FOO
ls: cannot access bar: No such file or directory
ls: cannot access baz: No such file or directory
Run Code Online (Sandbox Code Playgroud)
在zsh
,而另一方面,同样的三个命令成功。因此,基于此实验,似乎在 中bash
可以省略 内部的双引号[[ ... ]]
,但不能省略内部 …
当我想在bash
脚本中要求输入密码时,我会这样做:
read -s
Run Code Online (Sandbox Code Playgroud)
...但是当我bash
在 POSIX 模式下运行时sh
,该-s
选项被拒绝:
$ read -s
sh: 1: read: Illegal option -s
Run Code Online (Sandbox Code Playgroud)
如何使用符合 POSIX 的命令安全地请求输入?
当我打开一个 bash 提示符并输入:
$ set -o xtrace
$ x='~/someDirectory'
+ x='~/someDirectory'
$ echo $x
+ echo '~/someDirectory'
~/someDirectory
Run Code Online (Sandbox Code Playgroud)
我希望上面的第 5 行会出现+ echo /home/myUsername/someDirectory
。有没有办法做到这一点?在我的原始 Bash 脚本中,变量 x 实际上是从输入文件中的数据填充的,通过这样的循环:
while IFS= read line
do
params=($line)
echo ${params[0]}
done <"./someInputFile.txt"
Run Code Online (Sandbox Code Playgroud)
尽管如此,我得到了类似的结果,echo '~/someDirectory'
而不是echo /home/myUsername/someDirectory
.
在大多数符合 POSIX 标准的 shell 中,如bash
. ksh
, dash
, mksh
, pdksh
, 当变量赋值发生时,在赋值的 RHS 中不执行字段拆分和文件名扩展(如果 shell 支持,则扩展括号):
$ IFS=/
$ a=1/2
# Field splitting and filename expansion turned off here
$ b=$a
$ IFS=
$ printf '%s\n' $b
1/2
Run Code Online (Sandbox Code Playgroud)
一些 shell 的文档(bash,ksh)提到了这一点,但POSIX 文档没有。
我可以在大多数符合 POSIX 的 shell 中看到这种行为,所以我想知道它是否可移植,因为 POSIX 文档没有指定它?