xen*_*ide 184 shell shell-script environment-variables posix quoting
我可以写
VAR=$VAR1
VAR=${VAR1}
VAR="$VAR1"
VAR="${VAR1}"
Run Code Online (Sandbox Code Playgroud)
最终结果对我来说似乎都差不多。我为什么要写一个或另一个?这些中的任何一个都不是便携式/ POSIX 吗?
Sha*_*off 130
VAR=$VAR1是 的简化版VAR=${VAR1}。第二个可以做第一个不能做的事情,例如引用数组索引(不可移植)或删除子字符串(POSIX 可移植)。请参阅POSIX 规范中的初学者和参数扩展Bash 指南的更多变量部分。
在变量周围使用引号,例如rm -- "$VAR1"orrm -- "${VAR}"是一个好主意。这使得变量的内容成为一个原子单位。如果变量值包含空格(嗯,$IFS特殊变量中的字符,默认情况下为空格)或通配符并且您没有引用它,那么每个单词都被考虑用于文件名生成(通配符),其扩展会为您提供尽可能多的参数正在做。
$ find .
.
./*r*
./-rf
./another
./filename
./spaced filename
./another spaced filename
./another spaced filename/x
$ var='spaced filename'
# usually, 'spaced filename' would come from the output of some command and you weren't expecting it
$ rm $var
rm: cannot remove 'spaced': No such file or directory
# oops! I just ran 'rm spaced filename'
$ var='*r*'
$ rm $var
# expands to: 'rm' '-rf' '*r*' 'another spaced filename'
$ find .
.
./another
./spaced filename
./another spaced filename
$ var='another spaced filename'
$ rm -- "$var"
$ find .
.
./another
./spaced filename
Run Code Online (Sandbox Code Playgroud)
关于可移植性:根据POSIX.1-2008 section 2.6.2,花括号是可选的。
Gil*_*il' 71
${VAR}并且$VAR完全等效。对于普通的变量扩展,使用的唯一原因${VAR}是解析会在变量名中抓取太多字符,如${VAR1}_$VAR2(没有大括号相当于${VAR1_}$VAR2)。大多数修饰的扩展 ( ${VAR:=default}, ${VAR#prefix}, ...) 需要大括号。
在变量赋值中,字段拆分(即在值中的空白处拆分)和路径名扩展(即通配)被关闭,因此VAR=$VAR1完全等同于VAR="$VAR1", 在所有 POSIX shell 和所有我听说过的 pre-POSIX sh 中. (POSIX 参考:简单命令)。出于同样的原因,VAR=*可靠地设置VAR为文字字符串*;当然VAR=a b设置VAR为a因为首先b是一个单独的词。一般来说,在 shell 语法需要一个单词的地方,双引号是不必要的,例如incase … in(但不是在模式中),但即使在那里你也需要小心:例如 POSIX 指定重定向目标( >$filename) 不需要在脚本中引用,但包括 bash 在内的一些 shell 确实需要双引号,即使在脚本中也是如此。请参阅何时需要双引号?进行更彻底的分析。
在其他情况下,您确实需要双引号,特别export VAR="${VAR1}"是export "VAR=${VAR1}"在许多 shell 中(可以等效地写成)(POSIX 使这种情况保持打开状态)。这种情况与简单赋值的相似性,以及不需要双引号的情况列表的分散性质,就是为什么我建议只使用双引号的原因,除非您确实想要拆分和通配符。
SYA*_*iDE 12
考虑双引号用于变量扩展,而单引号用于强引用,即无扩展。
this='foo'
that='bar'
these="$this"
those='$that'
Run Code Online (Sandbox Code Playgroud)
for item in "$this" "$that" "$these" "$those"; do echo "$item"; done
foo
bar
foo
$that
Run Code Online (Sandbox Code Playgroud)
值得一提的是,出于多种原因,您应该尽可能使用引用,其中最好的原因是它被认为是最佳实践,并且为了可读性。也因为 Bash 有时很古怪,而且经常以看似不合逻辑或不合理/出乎意料的方式出现,并且引用将隐式期望更改为显式期望,从而减少了错误面(或其中的可能性)。
虽然不引用是完全合法的,并且在大多数情况下都可以使用,但提供该功能是为了方便,并且可能不太便携。保证反映意图和期望的完全正式的做法是引用。
现在还要考虑该构造"${somevar}"用于替换操作。几个用例,例如替换和数组。
thisfile='foobar.txt.bak'
foo="${thisfile%.*}" # removes shortest part of value in $thisfile matching after '%' from righthand side
bar="${thisfile%%.*}" # removes longest matching
for item in "$foo" "$bar"; do echo "$item"; done
foobar.txt
foobar
Run Code Online (Sandbox Code Playgroud)
foobar='Simplest, least effective, least powerful'
# ${var/find/replace_with}
foo="${foobar/least/most}" #single occurrence
bar="${foobar//least/most}" #global occurrence (all)
for item in "$foobar" "$foo" "$bar"; do echo "$item"; done
Simplest, least effective, least powerful
Simplest, most effective, least powerful
Simplest, most effective, most powerful
Run Code Online (Sandbox Code Playgroud)
mkdir temp
# create files foo.txt, bar.txt, foobar.txt in temp folder
touch temp/{foo,bar,foobar}.txt
# alpha is array of output from ls
alpha=($(ls temp/*))
echo "$alpha" # temp/foo.txt
echo "${alpha}" # temp/foo.txt
echo "${alpha[@]}" # temp/bar.txt temp/foobar.txt temp/foo.txt
echo "${#alpha}" # 12 # length of first element (implicit index [0])
echo "${#alpha[@]}" # 3 # number of elements
echo "${alpha[1]}" # temp/foobar.txt # second element
echo "${#alpha[1])" # 15 # length of second element
for item in "${alpha[@]}"; do echo "$item"; done
temp/bar.txt
temp/foobar.txt
temp/foo.txt
Run Code Online (Sandbox Code Playgroud)
所有这些都只是触及"${var}"替代结构的表面 。Bash shell 脚本的权威参考是 libre 在线参考,TLDP The Linux Documentation Projecthttps://www.tldp.org/LDP/abs/html/parameter-substitution.html