我不理解这行shell脚本。while语句难道不需要一个'test'或[ ]或[[ ]]表达式来将$?设置为1或0吗?这个脚本是如何运作的?
while IFS= read -r -d $'\0'; do ...; done
怎么做呢?非常感谢您帮忙理解这里的语法。
我不理解这行shell脚本。while语句难道不需要一个'test'或[ ]或[[ ]]表达式来将$?设置为1或0吗?这个脚本是如何运作的?
while IFS= read -r -d $'\0'; do ...; done
怎么做呢?非常感谢您帮忙理解这里的语法。
varname=value command
会将环境变量varname
设置为value
(并且所有其他环境变量都像通常继承一样)。因此,IFS= read -r -d $'\0'
会使用空字符串设置环境变量IFS
(意味着没有字段分隔符)来运行命令read -r -d $'\0'
。read
成功读取输入并且没有遇到文件结尾时返回成功(即将$?
设置为0
),因此总体效果是循环遍历一组以NUL分隔的记录(保存在变量REPLY
中)。
while语句不需要'test'或[ ]或[[ ]]表达式来将$?设置为1或0吗?
test
和[ ... ]
和[[ ... ]]
实际上不是表达式,而是命令。在Bash中,每个命令都会返回成功(将$?
设置为0
)或失败(将$?
设置为非零值,通常为1
)。-d $'\0'
等效于-d ''
。Bash变量在内部表示为C风格/NUL终止字符串,因此您实际上无法在字符串中包含NUL;例如,echo $'a\0b'
只打印a
。)while
语句的语法感到困惑,没有意识到可以使用任意语句。 - user743382$ touch foo.txt #Create a "foo.txt" file
$ ls foo.txt
foo.txt
$ echo $?
0
$
ls
命令返回了零值。现在尝试执行以下命令:$ rm foo.txt
$ ls foo.txt
ls: foo.txt: No such file or directory
$ echo $?
1
$
foo.txt
不存在,ls
命令返回退出代码 1。
if
和 while
命令可以操作这个退出代码。foo.txt
文件。然后返回原始窗口并尝试执行以下命令:$ while ls foo.txt > /dev/null
> do
> echo "The file foo.txt exists"
> sleep 2
> done
The file foo.txt exists
The file foo.txt exists
The file foo.txt exists
...
foo.txt
是否存在,并打印出相应的语句。现在,回到第二个终端窗口并删除foo.txt
。如果你回到第一个终端窗口,你会看到while
循环结束了。if
做同样的操作:$ if ls foo.txt > /dev/null
> then
> echo "foo.txt exists"
> else
> echo "Whoops, it's gone!"
> fi
这个if
语句将根据目录中是否存在名为foo.txt
的文件,打印出foo.txt存在或糟糕,它不见了!。
注意,if
和while
会根据命令的返回退出值进行操作。完全没有必要进行测试。
那么为什么需要test
、[...]
和[[...]]
语法呢?
假设您想要找出$foo
是否等于$bar
,这就是test
发挥作用的地方。试试这个:
$ foo=42
$ bar=42
$ test "$foo" -eq "$bar"
$ echo $?
0
$ bar=0
$ test "$foo" -eq "$bar"
$ echo $?
1
test命令只在测试结果为true时返回零,在测试结果为false时返回非零值。这使您可以在if
和while
语句中使用test
命令。
$ if test $foo -eq $bar
> then
> echo "foo is equal to bar"
> else
> echo "foo and bar are different"
> fi
foo and bar are different
$
[...]
是什么?$ ls -il /bin/test /bin/[
10958 -rwxr-xr-x 2 root wheel 18576 May 28 22:27 /bin/[
10958 -rwxr-xr-x 2 root wheel 18576 May 28 22:27 /bin/test
第一列是 inode。如果两个文件具有相同的 inode,则它们是 硬链接 并引用同一个文件。请注意,在我的系统上,它们都是 18,576 字节。
[
只是执行 test
命令的另一种方式。这两行命令是相同的:
if test $foo -eq $bar
if [ $foo -eq $bar ]
[
的作用是让shell脚本看起来更加美观。但是,在其内部,它运行了一个test
命令,该命令将返回一个零或非零值,可以被if
和while
所使用。[
和test
都是shell的内建命令。但是,它们引用了相同的内建命令。
[[...]]
是测试的一个特殊版本,最初出现在Kornshell中。它允许使用模式匹配,并且由于它不会生成另一个进程来运行test
命令,因此速度更快一些。ls
可能是演示目的的好选择,但在实际程序中使用它通常是一个错误。 - tripleeels
是一个易于理解且广为人知的命令。如果您想知道文件是否存在,请使用 [ -f ... ]
。 - David W.代码解释:
IFS=
将 IFS 设置为空(输入字段分隔符)read
命令读取当前行,具有以下选项:-r
:不允许反斜杠转义任何字符-d
:继续读取,直到读取 DELIM 的第一个字符,而不是换行符$'\0'
零字节(ASCII NUL 字符)请参见
help read
test
和表达式[[ ...]]
只是提供一个反映其包含的条件表达式真假的退出状态(唯一关心的事情是while
)的结构。$foo
的值为bar
,则[[ $foo = bar ]]
的退出状态为0(成功),否则为非零存在状态(具体为1)。
while
循环执行其主体,只要在while
关键字后面的命令的退出状态为0。在此代码中,只要read
可以从其输入中读取内容,它就具有0的退出状态。