局部变量赋值需要引号吗?

局部变量赋值需要引号吗?

我可以安全地省略本地作业右侧的引号吗?

function foo {
    local myvar=${bar}
    stuff()
}

我主要对 感兴趣bash,但欢迎任何有关其他 shell 中的极端情况的信息。

答案1

export foo="$var"or local foo="$var"(或readonly, typeset,declare以及其他变量声明中需要引号命令) 在:

  • dash版本 0.3.8-15 至 0.5.10.2(请参阅改变)。
  • NetBSD的sh(也基于 Almquist shell)。
  • shFreeBSD 9.2 或更早版本的(请参阅9.3 中的变化
  • yash
  • zsh5.1 之前的版本在kshsh仿真中(或在export var="$(cmd)"何处zsh执行分词,否则(不是通配符))。

否则,变量扩展将受到分词和/或文件名生成的影响,就像任何其他命令的任何参数一样。

并且在以下情况下不需要:

  • bash
  • ksh(所有实现)
  • FreeBSD sh9.3 或更新版本
  • busybox' 基于 ash sh(自 2005 年起)
  • zsh
  • dash0.5.11 或更高版本。

在 中zsh,split+glob 永远不会在参数扩展时完成,除非在shksh仿真中,但 split(不是 glob)是在命令替换时完成的。从5.1版本开始,export/local和其他声明命令变成了双重的关键词/内置像上面其他 shell 中的命令一样,这意味着不需要引用,即使在sh/ksh模拟中,甚至对于命令替换也是如此。

在某些特殊情况下,即使在这些 shell 中也需要引用,例如:

a="b=some value"
export "$a"

=或者更一般地说,如果(包括)的剩余部分=被引用或某些扩展的结果(例如export 'foo'="$var", export foo\="$var"or export foo$((n+=1))="$var"$((...))实际上也应该被引用)...)。或者换句话说,export如果在没有export.

如果export/local命令名称本身被引号引起来(即使部分像"export" a="$b"'ex'port a="$b"\export a="$b"、 甚至""export a="$b"),则需要引号,$b除了 AT&Tkshmksh最新版本的dash.

如果export/或它的某些部分是某些扩展的结果(例如 in或 Even )或类似)local的结果,则需要引号,但在最新版本的.cmd=export; "$cmd" a="$b"export$(:) a="$b"dryrun=; $dryrun export a="$b"dash

在 的情况下> /dev/null export a="$b",需要pdksh及其一些衍生品的报价。

对于command export a="$b",每个 shell 中都需要引号,但mkshksh93、最近的dash和 除外(对于和不是除 之外的 shell 中某些扩展的结果,也有bash -o posix相同的警告)。commandexportdash

编写时,任何 shell 中都不需要它们:

foo=$var export foo

(该语法也与 Bourne shell 兼容,但在最新版本的 中zsh,仅在sh/ksh模拟中有效)。

(请注意,var=value local var不应使用它,因为不同 shell 的行为有所不同)。

export另请注意,与赋值一起使用还意味着cmdin的退出状态export var="$(cmd)"丢失。这样做就export var; var=$(cmd)没有这个问题。

还要注意这种特殊情况bash

$ bash -c 'IFS=; export a="$*"; echo "$a"' bash a b
ab
$ bash -c 'IFS=; export a=$*; echo "$a"' bash a b
a b

我的建议是总是引用。

答案2

我通常会引用可能存在空格等字符的变量的任何用法。否则你会遇到这样的问题:

#!/bin/bash

bar="hi bye"

function foo {
  local myvar=${bar}
  printf "%s\n" $myvar
  printf "%s\n" "$myvar"
}

foo

赋值中变量的使用似乎不需要引号,但是当您要使用它时,例如在 中,printf您需要在那里引用它:

  printf "%s\n" "$myvar"

笔记:请记住,变量$IFS决定分隔符的内容。

IFS    The  Internal  Field  Separator that is used for word splitting after 
       expansion and to split lines into words with the read builtin command. 
       The default value is ``<space><tab><newline>''.

例子

通过在 Bash 中启用调试,我们可以看到幕后发生的情况。

$ bash -x cmd.bash 
+ bar='hi bye'
+ foo
+ local 'myvar=hi bye'
+ printf '%s\n' hi bye
hi
bye
+ printf '%s\n' 'hi bye'
hi bye

在上面我们可以看到,变量$bar被很好地传递给了,$myvar但是当我们使用它时,$myvar我们必须了解$myvar我们使用它时的内容。

相关内容