bash 脚本

bash 脚本

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

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

第二行发生了什么,什么[ x$1 = x ] 意思?

答案1

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

答案2

方括号表示测试,所以[ x$1 = x]没有if或类似的东西是没有意义的,尽管语法上没问题。

x$1如果扩展为,则计算结果为 true ,x否则为 false ,但由于它未加引号,如果$1是(例如)“hey x”,shell 将看到x = x,因此这种构造仍然不安全。

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

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

Bash 测试操作符-z-n可以使用,但它们对于其他类型的 shell 的可移植性较差。1

使用引号或 的原因x$1是为了使左侧不会扩展为空,这将是语法错误:

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

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

答案3

[ x$1 = x ]

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

[ $1 = "" ]

不起作用,因为zsh当列表上下文中未引用空变量时,它会扩展为根本没有参数而不是空参数,因此如果$1未设置或为空,则[命令将仅接收作为参数[, =,空字符串这是]无法理解的。[ -z "$1" ]或者[ "$1" = "" ]像在 POSIX shell 中那样也可以。

在 Bourne-like/POSIX shell 中,[ x$1 = x ]没有意义。这是 split+glob 运算符以某种方式应用于x脚本的第一个参数的串联,希望结果 和=x]组成[命令的有效测试表达式。

例如,如果脚本传递一个" = x -o x ="参数,[则将接收这些参数:[, x, =, x, -o, x, =, x, ],这[将被理解为xxx进行比较x并返回 true。

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

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

[ "x$1" = x ]

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

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

[ -z "$1" ]

但是,对于某些(非 POSIX)实现中的某些$1值(例如Solaris 10 及之前版本的 Bourne shell 中的内置值)或某些旧版本(最高至 0.5.4)或某些 BSD 的某些值,该方法会失败。=[/bin/shdashsh

这是因为[看到[-z=]抱怨=二元运算符缺少参数,而不是将其理解为-z应用于=字符串的一元运算符。

同样,if is or[ "$1" = "" ]的某些实现也会失败。[$1!(

在这些 shell/[实现中:

[ "x$1" = x ]

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

[ "" = "$1" ]

和:

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

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

当然,如果你想检查是否没有提供任何参数,你可以这样做:

[ "$#" -eq 0 ]

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

请注意,如今,[ -z "$var" ]是由 POSIX 明确指定的,并且在一致性实现中不会失败[(并且bash'[已经存在了几十年)。所以你应该能够在 POSIX sh 或bash脚本中依赖它。

答案4

[ x$1 = x ]$1如果unset/null/empty 则为true 。
尝试一下:
TEST= ;[ x$TEST = x] && echo "TEST is unset"

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

相关内容