我不明白这行shell脚本。 while语句是否需要设置$的'test'或[]或[[]]表达式?到1还是0?怎么做
while IFS= read -r -d $'\0'; do ...; done
那样做吗?非常感谢任何理解语法的帮助。
答案 0 :(得分:13)
在Bash中,varname=value command
运行命令,环境变量varname
设置为value
(并且所有其他环境变量都正常继承)。因此IFS= read -r -d $'\0'
运行命令read -r -d $'\0'
,并将环境变量IFS
设置为空字符串(表示没有字段分隔符)。
由于read
在成功读取输入并且没有遇到文件结尾时返回成功(即,将$?
设置为0
),因此总体效果是循环一组NUL分隔的记录(保存在变量REPLY
中)。
while语句是否需要设置$的'test'或[]或[[]]表达式?到1还是0?
test
和[ ... ]
以及[[ ... ]]
实际上不是表达式,而是命令。在Bash中,每个命令都会返回成功(将$?
设置为0
)或失败(将$?
设置为非零值,通常为{{1} })。
(顺便说一句,正如上面评论中的nosid注释,1
相当于-d $'\0'
。Bash变量在内部表示为C风格/ NUL终止字符串,所以你不能真正在字符串中包含NUL;例如,-d ''
只打印echo $'a\0b'
。)
答案 1 :(得分:3)
我不明白这行shell脚本。 while语句是否需要设置$的'test'或[]或[[]]表达式?到1还是0? [声明]如何做到这一点?
每个人都在回答-d
和IFS=
参数,但没有人回答您关于test
和[[..]]
的问题。
所有标准Unix命令将在成功时返回零值,在退出时返回非零值。 while
和if
语句使用该值来确定是否继续循环:
假设您执行以下操作:
$ 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
...
每隔两秒,while将循环检查是否存在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 exists 或 Whoops,它已消失!取决于是否存在名为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
所有测试命令都会在 true 测试中返回零,在 false 测试中返回非零值。这允许您在test
和if
语句中使用while
命令。
$ 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
可以使用的零或非零值。
顺便说一下,在Kornshell和BASH中,[
和test
都是内置到shell。但是,它们确实引用了相同的内置命令。
[[...]]
是首次出现在Kornshell中的特殊测试版本。它允许使用模式匹配,并且它更快一些,因为它不会产生另一个进程来运行test
命令。
答案 2 :(得分:2)
代码说明:
IFS=
将IFS设置为null(输入fiels分隔符)read
命令,使用以下选项读取当前行:-r
:不允许反斜杠转义任何字符-d
一直持续到读取DELIM的第一个字符,而不是换行符$'\0'
零字节(ASCII NUL字符)见
help read
答案 3 :(得分:2)
没有。 test
命令和[[ ...]]
表达式只是提供反映其包含的条件表达式真实性的退出状态(唯一while
关心的东西)的构造。
例如,如果[[ $foo = bar ]]
的值为$foo
,则bar
的退出状态为0(成功),否则为非零存在状态(具体为1)。
只要while
关键字后面的命令的退出状态为0,while
循环就会执行其正文。在此代码中,read
的退出状态为0,只要它可以从输入中读取内容。