VAR=$VAR1
VAR=${VAR1}
VAR="$VAR1"
VAR="${VAR1}"
我的最终结果似乎都差不多。我为什么要写一个或另一个?这些不是便携式/ POSIX吗?
#1 楼
VAR=$VAR1
是VAR=${VAR1}
的简化版本。第二个东西可以做一些第一个不能做的事情,例如引用数组索引(不可移植)或删除子字符串(POSIX便携式)。请参阅POSIX规范中Bash初学者和参数扩展指南的“更多关于变量”部分。在
rm -- "$VAR1"
或rm -- "${VAR}"
中使用变量引号是个好主意。这使变量的内容成为原子单位。如果变量值包含空格(嗯,$IFS
特殊变量中的字符,默认情况下为空格)或不带引号的字符,则不考虑每个单词的文件名生成(globbing),其扩展会为任意内容扩展尽可能多的参数$ 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
关于可移植性:
根据POSIX.1-2008第2.6.2节,花括号是可选的。
#2 楼
${VAR}
和$VAR
完全等效。对于普通的变量扩展,使用${VAR}
的唯一原因是在解析时否则会在变量名中捕获太多字符,如${VAR1}_$VAR2
(不带花括号将等同于${VAR1_}$VAR2
)。大多数经过修饰的扩展(${VAR:=default}
,${VAR#prefix}
…)都需要大括号。在变量赋值中,字段拆分(即,在值的空白处拆分)和路径名扩展(即,globbing)已关闭,因此
VAR=$VAR1
在我听说过的所有POSIX shell和所有POSIX之前的sh中,它完全等同于VAR="$VAR1"
。 (POSIX参考:简单命令)。由于相同的原因,VAR=*
可靠地将VAR
设置为文字字符串*
;当然,由于VAR=a b
首先是一个单独的单词,因此VAR
会将a
设置为b
。一般而言,在shell语法需要一个单词的情况下,例如在case … in
中(但不在模式中),双引号是不必要的,但是即使在那儿也需要小心:例如POSIX指定重定向目标(>$filename
)不需要在脚本中加引号,但是即使在脚本中,包括bash在内的一些shell都需要双引号。请参阅何时需要双引号?为了进行更彻底的分析。在其他情况下,尤其是在许多shell中,特别是在export VAR="${VAR1}"
(可以等效地写为export "VAR=${VAR1}"
)中,确实需要双引号(POSIX使此例保持打开状态)。这种情况与简单赋值的相似性,以及不需要双引号的情况列表的分散性质,这就是为什么我建议仅使用双引号的原因,除非您确实希望拆分和使用glob。评论
通常,即使我知道该值将不包含任何IFS字符(因为我想养成习惯),我也总是引用变量扩展名。一个例外是我在进行变量赋值时不引用该值(除非需要,例如,当值包含空格时)。当存在命令替换,例如FOO = $(BAR = $(BAZ = blah; printf%s“ $ {BAZ}”); printf%s“ $ {BAR}”)时,这使编辑器语法突出显示更加有用。而不是为所有内容都加上“字符串”颜色,而是让嵌套代码的语法高亮显示。这也是为什么我避免反引号的原因。
–理查德·汉森(Richard Hansen)
2013年1月4日19:19
虽然在POSIX脚本中> $ file是可以的,但即使是非交互式的,它也不是bash(除非使用$ POSIXLY_CORRECT或--posix ...强制执行POSIX遵从性)。
–StéphaneChazelas
13年1月23日在15:01
虽然确实在VAR = $ VAR1中不需要引号,但有时我对本地VAR = $ VAR1感到惊讶,我记得在某些方面,至少在某些外壳中,它们的工作方式有所不同。但是atm,我无法重现这种分歧。
– dubiousjim
2015年9月19日上午8:31
好的,找到了我记得的问题。它仅在某些外壳中显示。
– dubiousjim
2015年9月19日上午10:47
@dubiousjim本地VAR = $ VAR1类似于export VAR = $ VAR1,它取决于外壳程序。
–吉尔斯'所以-不再是邪恶的'
2015年9月19日下午13:17
#3 楼
引用考虑将双引号用于变量扩展,将单引号用于强引号(即无扩展)。
扩展:
this='foo'
that='bar'
these="$this"
those='$that'
输出:
for item in "$this" "$that" "$these" "$those"; do echo "$item"; done
foo
bar
foo
$that
值得一提的是,出于多种原因,应尽可能使用引号最好的是,它被认为是最佳实践,并且具有可读性。同样是因为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
替换(替换):
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
数组:
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
所有这些几乎没有刮伤
"${var}"
替代结构的表面。 Bash shell脚本的权威参考是免费在线参考TLDP Linux文档项目https://www.tldp.org/LDP/abs/html/parameter-substitution.html
评论
非常有用。
– Orion elenzil
19 Mar 20 '19在17:04
当您只知道大约1%的家庭黑客对bash变量引用有所了解时。
– RichieHH
20 Dec 26'5:37
#4 楼
ls -la
lrwxrwxrwx. 1 root root 31 Nov 17 13:13 prodhostname
lrwxrwxrwx. 1 root root 33 Nov 17 13:13 testhostname
lrwxrwxrwx. 1 root root 32 Nov 17 13:13 justname
然后结束:
env=
if [ ! -f /dirname/${env}hostname ]
值得一提的是使用冰壶的更清晰示例
评论
@shawn更新了我的问题,因为我也对可移植性感到好奇
– xenoterracide
2010-12-16 13:46
@shawn:我怀疑你的例子是正确的。您是否有shell的真实示例,其中var1 = $ var扩展给出错误?
– alex
2010-12-16 14:48
@alex:谢谢。我以为我已经在命令行上进行了测试,但是我做错了。我改变了例子。
– Shawn J. Goff
2010-12-16 15:19
对于更新后的示例,最好记住您通常应该使用引用的版本,因为该示例相当简单。
– alex
2010-12-16在16:15
@Shawn:作业中不需要引号。它们在大多数其他用途中都是必需的,包括导出VAR = $ VAR1。至于花括号,它们是可选的(请检查所引用部分的第四段;在所有POSIX和POSIX之前的外壳中都是这种情况)。
–吉尔斯'所以-不再是邪恶的'
2010-12-16 19:13