【问题标题】:Reason of adding "_" in the if comparison "if [ "_$str" = "_" ]; then ....; fi"在 if 比较 "if [ "_$str" = "_" ]; then ....; fi" 中添加 "_" 的原因
【发布时间】:2013-09-17 13:05:38
【问题描述】:

我在 shell 脚本中多次看到他们在 if 比较中使用 "_",如下所示:

if [ "_$str" = "_" ]; then ....; fi

上面的代码通过比较if [ "_$str" = "_" ]检查str变量是否为空。

为什么不用if [ "$str" = "" ]?为什么要在两个字符串中添加"_"

【问题讨论】:

  • 这似乎是跳过空字符串比较的好方法。在两个字符串中附加一个字符可以避免极端情况并保留结果。
  • 只需使用[ -z "${str}" ]
  • @devnull 有趣的是,该命令将在受影响的 shell 中间接成功。如果$str 为空,扩展将被错误地删除,留下[ -z ]。但是,这可能会被视为非空字符串(不是运算符-z),无论如何都会评估为真。

标签: linux bash shell sh


【解决方案1】:

据我所知,这是出于历史原因。曾经有(并且可能在一些不为人知的系统上仍然存在)shell 在处理空字符串(并且可能以破折号开头的字符串)时遇到了问题。因此,通过添加前缀来完全防止空字符串(和类似选项的字符串)的简单想法。今天所有常见的shell都不再有这些问题了。

【讨论】:

  • 这是我在 1992 年左右第一次看到它时听到的原因。所以今天可能是出于古代或史前的原因。
【解决方案2】:

我只能猜测,在学习如何正确使用引号之前,您所看到的脚本的作者遇到了类似的问题

if [[ $str = "" ]]; then ....

如果 $str 为空,它将失败,因为参数扩展为空。而

if [[ _$str = _ ]]

会起作用,但是是个杂牌。

【讨论】:

  • 问题早于bash 中的[[...]] 表达式(它可以很好地处理空值参数的扩展),实际上是处理引用的空值参数的真正错误旧 Bourne shell 中的 test 命令。
【解决方案3】:

请记住,[ 是命令 test 的别名。问题是如果你的字符串以破折号开头会发生什么?

在旧版本的 test 中使用标准 Bourne shell 时,您会收到错误:

$ test -gt = "some_string"
invalid argument

if 也会发生同样的事情

$ string="-gt"
$ if [ "$string" = "some_other_string" ]
> then
> echo "Match"
> else
> echo "No Match"
> fi
if: invalid argument

这是因为test 命令会看到带有破折号的参数并假定它是命令参数,那么要么是无效的命令参数,要么命令的格式不正确。如果您使用[[ 而不是[,这根本不是问题,因为[[if 的内置测试。

这不再是问题。 [test 是 Kornshell 和 BASH 的内部命令,这些 shell 可以处理这个问题。即使是较新版本的 test 也不再抛出:

$ test -gt = "some_string"  # No error.
$ echo $?
1

但是,较旧的脚本,以及那些从较旧的计时器那里学习的人,或者在使用 Xenix 的 16 Mhz 386 芯片上运行 32 Mb 内存的系统是最先进的系统时重新编写脚本的人已经进入习惯。我以前用x:

if [ x$var = x$foo ]

【讨论】:

  • +1 用于提示参数以破折号开头的问题(因此不仅空字符串可能会造成问题)。
  • @Alfe 如果用引号将字符串括起来,这不是问题。即使一个或另一个变量为空,[ "$foo" = "$bar" ] 也可以。但是,没有引号是一个问题。 [ $foo = $bar ] 可能会导致问题。
  • 忘记引号一直是并且现在仍然是一个问题。作为此处主题的前缀事物与正确的引用无关。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-10-01
  • 1970-01-01
  • 2017-05-13
  • 1970-01-01
  • 1970-01-01
  • 2012-09-09
  • 1970-01-01
相关资源
最近更新 更多