it-swarm.cn

$ VAR vs $ {VAR}并引用或不引用

我会写

VAR=$VAR1
VAR=${VAR1}
VAR="$VAR1"
VAR="${VAR1}"

对我来说,最终结果似乎差不多。我为什么要写一个或另一个?这些不是便携式/ POSIX吗?

150
xenoterracide

VAR=$VAR1VAR=${VAR1}的简化版本。第二个东西可以做一些第一个不能做的事情,例如引用数组索引(不可移植)或删除子字符串(POSIX便携式)。请参阅《 Bash初学者指南》中的 关于变量的更多信息 部分和POSIX规范中的 参数扩展

rm -- "$VAR1"rm -- "${VAR}"中对变量使用引号是一个好主意。这使变量的内容成为原子单位。如果变量值包含空格(或者,$IFS特殊变量中的字符,默认情况下为空格)或不带引号的字符,并且您不引用它,则每个Word都将考虑用于文件名生成(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节 ,花括号是可选的。

108
Shawn J. Goff

${VAR}$VAR完全相同。对于普通的变量扩展,使用${VAR}的唯一原因是在解析时否则会在变量名中捕获太多字符,如${VAR1}_$VAR2(不带大括号的等效于${VAR1_}$VAR2 )。装饰最多的扩展(${VAR:=default}${VAR#prefix},...)都需要大括号。

在变量赋值中, 字段拆分 (即在值的空白处拆分)和 路径名扩展 (即通配符)处于关闭状态,因此VAR=$VAR1完全等效我听说过的所有POSIX Shell和所有POSIX之前版本中的_VAR="$VAR1"。 (POSIX参考: 简单命令 )。由于相同的原因,VAR=*可靠地将VAR设置为文字字符串*;当然VAR=a bVAR设置为a,因为b首先是一个单独的单词。一般来说,如果Shell语法需要一个单词,则不需要双引号,例如 case … in (但不在模式中),但是即使在那儿也需要小心:例如POSIX指定 重定向目标>$filename)不需要在脚本中使用引号,但是包括bash在内的一些shell甚至在脚本中也需要使用双引号。请参阅 何时需要双引号? 以进行更全面的分析。

在其他情况下,您确实需要双引号,特别是在许多shell中(尤其是export VAR="${VAR1}"(可以等效地写为export "VAR=${VAR1}"))(POSIX使这种情况保持打开状态)。这种情况与简单赋值的相似性,以及不需要双引号的情况列表的分散性质,这就是为什么我建议仅使用双引号的原因,除非您确实希望拆分和使用glob。

65

报价单

考虑将双引号用于变量扩展,将单引号用于强引号,即无扩展。

扩张:

this='foo'
that='bar'
these="$this"
those='$that'

输出:

for item in "$this" "$that" "$these" "$those"; do echo "$item"; done
foo
bar
foo
$that

值得一提的是,出于多种原因,应尽可能使用引号,其中最好的一个是,它被认为是最佳实践,并且具有可读性。同样是因为Bash有时很古怪,而且常常是看似不合逻辑或不合理/意外的方式,而且引号将隐式期望更改为显式期望,从而减少了错误表面(或潜在错误)。

尽管使用not引用是完全合法的,并且在大多数情况下都可以使用,但该功能是为了方便起见而提供的,可能不太便于移植。保证体现意图和期望的正式实践是引用。

代换

现在还要考虑构造"${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

9
SYANiDE
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=$1
    if [ ! -f /dirname/${env}hostname ]

值得一提的是使用冰壶的更清晰示例

0
ninjabber