mur*_*uru 14

关于变量赋值需要注意的一件事是它们是 shell 语法中的一种特殊情况。来自 Bash 文档,在3.7.1 简单命令扩展中:

\n
\n

每个变量赋值中\xe2\x80\x98 \xe2\x80\x99 之后的文本=在赋值给变量之前都会经历波形符扩展、参数扩展、命令替换、算术扩展和引号删除。

\n
\n

然而,一般来说,令牌也会经历字段分割和文件名扩展(参见3.5 Shell 扩展),但这些不会在变量 asisgnment 期间执行

\n

这意味着在以下情况下,未引用的内容会受到不同的处理: $foo

\n
some-command $foo\nbar=$foo\n
Run Code Online (Sandbox Code Playgroud)\n

比方说foo=\'/* a b c */\'。(* a b c *是一个完全有效的目录名称,因此/* a b c */也是一个完全有效的目录路径。) 对于some-command $foo,它首先变得好像您编写了:

\n
some-command /* a b c */\n
Run Code Online (Sandbox Code Playgroud)\n

然后由 shell 扩展为:

\n
some-command /bin /boot ... a b c dir1/ dir2/ ...\n
Run Code Online (Sandbox Code Playgroud)\n

但对于 来说bar=$foo,情况并非如此。字段分割和文件名扩展都不会完成,并且它将保持原样 -bar将具有值/* a b c */。但是,如果您随后这样做some-other-command $bar,那么它将进行字段分割和文件名扩展。

\n

不过,在这两种情况下,引用"$foo"都会有相同的行为:

\n
some-command "$foo" # no field splitting, no filename expansion\nbar="$foo"          # equivalent to bar=$foo\n
Run Code Online (Sandbox Code Playgroud)\n

一些经验法则:

\n
    \n
  1. 如果您的值具有 shell 元字符,那么您必须至少引用这些元字符。元字符是:

    \n
    \n

    当不加引号时,用于分隔单词的字符。元字符是\n spacetabnewline或下列字符之一: \xe2\x80\x98 |\xe2\x80\x99,\n\xe2\x80\x98 &\xe2\x80\x99, \xe2\x80\x98 ;\xe2\x80\x99、\xe2\x80\x98 (\xe2\x80\x99、\xe2\x80\x98 )\xe2\x80\x99、\xe2\x80\x98 <\xe2\x80\x99 或 \xe2\ x80\x98 >\xe2\x80\x99。

    \n
    \n
  2. \n
  3. 如果该值具有!, 并且启用了历史扩展(交互式 shell 中通常是这种情况),则至少需要!使用单引号或反斜杠来引用。双引号是不够的。

    \n
  4. \n
  5. 如果该值具有 a~并且您希望进行波形符扩展,则“波形符前缀” 必须不加引号(因此~/in "/some/path":~/"bar"、 或~user/in~user/".config/app"等)。这使得可以将波形符扩展与包含空格等的路径混合在一起(so ~user/"some path (with metacharacters)")。

    \n
  6. \n
  7. 如果该值具有参数扩展($foo${foo}等)、命令替换($(bar)、 或`foo`)、算术扩展($((a+b)))或类似的内容,则:

    \n
      \n
    1. 如果您不想执行扩展,请用单引号将它们引起来。$您还可以使用反斜杠,但是仅在 中转义是不够的$((如上所述,元字符也是如此,也需要用引号引起来。
    2. \n
    3. 如果您希望扩展它们,则不引用它们也可以,或者您可以使用双引号。
    4. \n
    \n
  8. \n
  9. 如果该值中有过程替换(>(...)<(...)),则仅当替换未加引号时才会执行。

    \n
  10. \n
\n
\n

数组与常规赋值是不同的游戏。一般来说,(...)for内部的部分a=(...)就像命令行中其他任何地方一样被扩展,因此执行字段分割和文件名扩展。这使得可以执行以下操作:

\n
set -f\nIFS=:\npath=($PATH)\n
Run Code Online (Sandbox Code Playgroud)\n

$PATH并将条目作为数组中的单独项目获取path

\n


Art*_*ild 7

根据Bash 参考手册,没有“标准” 。

变量(Shell 参数)

可以通过以下形式的语句将变量赋值给

name=[value]
Run Code Online (Sandbox Code Playgroud)

引用

引用用于删除某些字符或单词对 shell 的特殊含义。引号可用于禁用对特殊字符的特殊处理,以防止保留字被识别为此类,并防止参数扩展。

在服务器系统上,默认文件名通常是标准字母数字字符,不包含任何特殊字符,并且通常不需要引用尽管可能存在例外)。

然而,在桌面系统上,更常见的是文件名包含空格和其他特殊字符,然后应该引用路径 - 这通常被认为是“安全路径”。

如果引用,请使用符合您需要的引号:单引号将按字面意思对待每个字符,而双引号仍会将$, `,\!视为特殊字符。

但是引用的标准对于分配变量的语法是不同的,因此它完全取决于变量的上下文(在本例中为文件名)。


Sto*_*ord 5

无引号示例:

filePath=Documents Folder 2
echo "$filePath"
Run Code Online (Sandbox Code Playgroud)

这将回显Documents
第一个空格之后的所有内容都将丢失。您需要引号才能保留空格。不使用引号仅适用于单个单词,但通常不被认为是一个好的做法。无论如何,最好使用引号。

双引号示例:

filePath="$HOME/Documents"
echo "$filePath"
Run Code Online (Sandbox Code Playgroud)

这将回显/home/用户名/Documents

单引号示例:

filePath='$HOME/Documents'
echo "$filePath" 
Run Code Online (Sandbox Code Playgroud)

这将回显$HOME/Documents

如果您希望系统按原样使用字符,请使用单引号。
如果您希望系统处理变量或其他特殊用途,请使用双引号。

  • 第一个示例尝试运行“Folder”(带有参数“2”),并将“filePath”在其环境中设置为“Documents”,但在当前 shell 中_未_设置“filePath”。如果它为您“回显”“文档”,则您必须之前设置该值。 (9认同)