Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/28.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Linux 何时在shell变量周围加引号?_Linux_Bash_Shell_Unix_Quotes - Fatal编程技术网

Linux 何时在shell变量周围加引号?

Linux 何时在shell变量周围加引号?,linux,bash,shell,unix,quotes,Linux,Bash,Shell,Unix,Quotes,有人能告诉我是否应该在shell脚本中用引号括住变量吗 例如,以下各项是否正确: xdg-open $URL [ $? -eq 2 ] 或 如果是,原因是什么?一般规则:如果它可以是空的,或者包含空格(或者任何空格)或者特殊字符(通配符),则引用它。不引用带空格的字符串通常会导致shell将单个参数分解为多个参数 $?不需要引号,因为它是一个数值。$URL是否需要它取决于您在其中允许的内容,以及如果参数为空,是否仍然需要参数 出于习惯,我总是引用字符串,因为这样更安全。一般规则:如果字符串可

有人能告诉我是否应该在shell脚本中用引号括住变量吗

例如,以下各项是否正确:

xdg-open $URL 
[ $? -eq 2 ]


如果是,原因是什么?

一般规则:如果它可以是空的,或者包含空格(或者任何空格)或者特殊字符(通配符),则引用它。不引用带空格的字符串通常会导致shell将单个参数分解为多个参数

$?
不需要引号,因为它是一个数值。
$URL
是否需要它取决于您在其中允许的内容,以及如果参数为空,是否仍然需要参数


出于习惯,我总是引用字符串,因为这样更安全。

一般规则:如果字符串可以是空的或包含空格(或任何空格)或特殊字符(通配符),则引用它。不引用带空格的字符串通常会导致shell将单个参数分解为多个参数

$?
不需要引号,因为它是一个数值。
$URL
是否需要它取决于您在其中允许的内容,以及如果参数为空,是否仍然需要参数


出于习惯,我总是引用字符串,因为这样更安全。

简而言之,在不需要shell执行令牌拆分和通配符扩展的地方引用所有内容

单引号逐字保护它们之间的文本。当您需要确保外壳完全不接触管柱时,它是合适的工具。通常,在不需要变量插值的情况下,它是引用机制的选择

$ echo 'Nothing \t in here $will change'
Nothing \t in here $will change

$ grep -F '@&$*!!' file /dev/null
file:I can't get this @&$*!! quoting right.
当需要变量插值时,双引号是合适的。通过适当的调整,当字符串中需要单引号时,它也是一个很好的解决方法。(单引号之间没有直接的转义方法,因为单引号内没有转义机制——如果有,它们不会完全逐字引用。)

当您特别要求shell执行令牌拆分和/或通配符扩展时,不使用引号

令牌拆分

 $ words="foo bar baz"
 $ for word in $words; do
 >   echo "$word"
 > done
 foo
 bar
 baz
相比之下:

 $ for word in "$words"; do echo "$word"; done
 foo bar baz
$ ls "$pattern"
ls: cannot access file*.txt: No such file or directory
(循环仅在单个带引号的字符串上运行一次。)

(循环仅在文字单引号字符串上运行一次。)

通配符扩展:

$ pattern='file*.txt'
$ ls $pattern
file1.txt      file_other.txt
相比之下:

 $ for word in "$words"; do echo "$word"; done
 foo bar baz
$ ls "$pattern"
ls: cannot access file*.txt: No such file or directory
(没有按字面命名的文件
file*.txt

(也没有名为
$pattern
的文件!)

更具体地说,任何包含文件名的内容通常都应该被引用(因为文件名可以包含空格和其他shell元字符)。任何包含URL的内容通常都应该被引用(因为许多URL包含shell元字符,如
&
)。任何包含正则表达式的内容通常都应该被引用(同上)。除非空白字符之间的单个空格外,任何包含重要空白的字符都需要被引用(因为否则,shell将把空白有效地咀嚼成单个空格,并修剪任何前导或尾随的空白)

当您知道变量只能包含不包含shell元字符的值时,引号是可选的。因此,不带引号的
$?
基本上是可以的,因为这个变量只能包含一个数字。但是,
“$?”
也是正确的,并且建议保持总体一致性和正确性(尽管这是我个人的建议,不是一项公认的政策)

非变量的值基本上遵循相同的规则,不过也可以转义任何元字符而不是引用它们。对于一个常见的示例,除非转义或引用元字符,否则shell将解析包含
&
的URL作为后台命令:

$ wget http://example.com/q&uack
[1] wget http://example.com/q
-bash: uack: command not found
(当然,如果URL位于未加引号的变量中,也会发生这种情况。)对于静态字符串,单引号最有意义,尽管任何形式的引号或转义都可以在这里使用

wget 'http://example.com/q&uack'  # Single quotes preferred for a static string
wget "http://example.com/q&uack"  # Double quotes work here, too (no $ or ` in the value)
wget http://example.com/q\&uack   # Backslash escape
wget http://example.com/q'&'uack  # Only the metacharacter really needs quoting
最后一个例子还提出了另一个有用的概念,我喜欢称之为“跷跷板引用”。如果需要混合使用单引号和双引号,可以相邻使用它们。例如,以下带引号的字符串

'$HOME '
"isn't"
' where `<3'
"' is."
(在后一个示例中,循环是完全多余的;
printf
特别适用于多个参数。
stat
也是如此。但是在通配符匹配上循环是一个常见的问题,并且经常做得不正确。)


包含要循环的令牌列表或要扩展的通配符的变量不太常见,因此我们有时缩写为“引用所有内容,除非您确切知道自己在做什么”。

简而言之,在不需要shell执行令牌拆分和通配符扩展的情况下,引用所有内容

单引号逐字保护它们之间的文本。当您需要确保外壳完全不接触管柱时,它是合适的工具。通常,在不需要变量插值的情况下,它是引用机制的选择

$ echo 'Nothing \t in here $will change'
Nothing \t in here $will change

$ grep -F '@&$*!!' file /dev/null
file:I can't get this @&$*!! quoting right.
当需要变量插值时,双引号是合适的。通过适当的调整,当字符串中需要单引号时,它也是一个很好的解决方法。(单引号之间没有直接的转义方法,因为单引号内没有转义机制——如果有,它们不会完全逐字引用。)

当您特别要求shell执行令牌拆分和/或通配符扩展时,不使用引号

令牌拆分

 $ words="foo bar baz"
 $ for word in $words; do
 >   echo "$word"
 > done
 foo
 bar
 baz
相比之下:

 $ for word in "$words"; do echo "$word"; done
 foo bar baz
$ ls "$pattern"
ls: cannot access file*.txt: No such file or directory
(循环仅在单个带引号的字符串上运行一次。)

(循环仅在文字单引号字符串上运行一次。)

通配符扩展:

$ pattern='file*.txt'
$ ls $pattern
file1.txt      file_other.txt
相比之下:

 $ for word in "$words"; do echo "$word"; done
 foo bar baz
$ ls "$pattern"
ls: cannot access file*.txt: No such file or directory
(没有按字面命名的文件
file*.txt

(也没有名为
$pattern
的文件!)

更具体地说,任何包含文件名的东西都应该是我们的