bash脚本[x $ 1 = x]


21

我正在阅读bash脚本,但我不明白那里发生了什么。

#!/bin/sh
[ x$1 = x ] 

第二行是什么[ x$1 = x ] 意思?

Answers:


27

该检查是否$1为空,尽管应将其引号(与相同[ -z "$1" ])。一些非常旧的shell无法正确处理空字符串,因此可移植脚本的编写者采用了这种检查方式。几十年来,它一直没有必要,但是人们仍然那样做,因为人们仍然那样做。


是的,您不应该再像这样,而是采用更现代的风格。除非您正在使用PDP11。
MacLemon 2014年

4
与空字符串无关。[ x$1 = x ]仍是不正确的,但[ "x$1" = x ]将是有一个问题,即壳$1!(-n.... [ "" = "$1" ]并且case $1 in "")也将是OK,但。
斯特凡Chazelas

2
@MacLemon,无需再回头了。[ -z "$1" ]并且[ "$1" = "" ]仍然不能与Solaris 10的/ bin / sh一起使用,前者的破折号为dash-0.5.4。
斯特凡Chazelas

1
最后一句话额外+1!
glenn jackman 2014年

1
@glennjackman,最后一句话不正确。Solaris 10仍然是Solaris上部署最广泛的版本,并且[ "$1" = "" ]仍无法与其/bin/sh一起使用(尽管您想在/usr/xpg4/bin/sh此处使用而不是/bin/sh)。在2009
StéphaneChazelas 2014年

8

方括号表示测试,因此从语法上讲,[ x$1 = x]没有if或类似的内容没有意义。

它的意思是如果x$1扩展为x,则为true,否则为false,但由于未引用,因此如果$1是(例如)“嘿x”,则外壳程序将看到x = x,因此此构造仍不安全。

x = x检查的目的是确定变量是否为空。一种更常见的方法是使用引号:

if [ "$1" = "" ]; then

击测试运营商-z-n也可以使用,但它们对其他类型的炮弹的可移植性。1个

用引号或的原因x$1是,左手侧不会扩展为零,这是一个语法错误:

if [  = x ]  # No good!
if [ "" =  "" ] # Okay.
if [ x = x ] # Also okay.

1.实际上,它test可以是独立的实用程序,但是大多数外壳将其作为内置程序来实现;检查之间的差异which testtype test。在GNU / Linux上,它man test声称是指内置函数,但如果您调用(eg)/usr/bin/test,该实用程序似乎实现了手册页中记录的功能,包括-z-n


1
[ x$1 = x ]如果$1是,也将评估为true " -o x"。尝试sh -xc '[ x$1 = x ] && echo yes' sh ' -o x'[ x$1 = x ]是错误的,没有道理。
斯特凡Chazelas

@StéphaneChazelas感谢SC-编辑(第二段)。
goldilocks 2014年

您不需要if使用test,您可以在使用之前或之后使用它 &&||while使用$?
Jasen 2015年

8
[ x$1 = x ]

仅在中有意义zsh。它将的串联x与脚本的第一个参数进行比较x。因此,[如果$1为空或未提供,该命令将返回true 。

[ $1 = "" ]

之所以不起作用,zsh是因为在列表上下文中未引用空变量的情况下,该变量将扩展为无参数而不是空参数,因此如果未$1设置或为空,则该[命令将仅接收作为参数[=空字符串而]这是没有道理的。[ -z "$1" ]还是[ "$1" = "" ]可以的,尽管就像在POSIX shell中一样。

在类似Bourne / POSIX的外壳中,[ x$1 = x ]这没有任何意义。这就是割裂+水珠运营商莫名其妙地应用到的串联x和脚本的希望的结果,第一个参数=x,并]弥补有效的测试表情[命令。

举例来说,如果脚本传递一个" = x -o x ="参数,[将接收这些参数:[x=x-ox=x],这[所理解的比较xxx使用x并返回true。

如果$1"* *",则shell会将[当前目录中名称以x(的glob扩展名)开头的文件列表传递给命令x*,然后将非隐藏文件的列表(扩展名*)传递给命令...这[不太可能使任何意义。唯一有意义的情况是$1不包含通配符或空白字符。

现在,您有时会发现如下代码:

[ "x$1" = x ]

用于测试是否$1为空或未设置。

测试空变量或未设置变量的正常方法是:

[ -z "$1" ]

但是,对于失败的某些值$1就像=在某些(非POSIX)[如发现像内建一个在Bourne shell的实现/bin/sh在Solaris 10和前或一些老版本的dash(高达0.5.4)或sh一些BSD系统的。

这是因为[看见[-z=]并抱怨缺少的参数传递给=二元运算符,而不是理解它作为-z适用于单目运算符=串。

同样,[ "$1" = "" ]对于is is 或[if的某些实现失败。$1!(

在这些shell / [实现中:

[ "x$1" = x ]

无论的值如何,始终是有效的测试$1,因此:

[ "" = "$1" ]

和:

[ -z "${1:+x}" ]

case $1 in "") ...; esac

当然,如果要检查是否未提供任何参数,则可以执行以下操作:

[ "$#" -eq 0 ]

也就是说,您检查传递给脚本的参数数量。

请注意,现在,[ -z "$var" ]显然是由POSIX的规定和符合性不能不[实现(和bash[是,并已经有几十年)。因此,您应该能够在POSIX sh或bash脚本中依赖它。


0

x$1是连接两个字符串x$1并且如果$ 1为空,则x $ 1等于x,结果[x $ 1 = x]为true。x = y用于比较sh中的字符串


2
No x$1不会被引用,因此会对它们进行拆分和遍历。
斯特凡Chazelas

0

[ x$1 = x ]如果$1未设置/为空/为空,则为true 。
试试看:
TEST= ;[ x$TEST = x] && echo "TEST is unset"

TEST=lolz ;[ x$TEST = x ] && echo "TEST is unset"


1
[ x$1 = x ]如果$1是,也是如此" -o x"。尝试sh -xc '[ x$1 = x ] && echo yes' sh ' -o x'[ x$1 = x ]是错误的,没有道理。
斯特凡Chazelas
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.