我不明白这行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
去做?非常感谢您理解此处的语法的任何帮助。
在 Bash 中,运行命令并将环境变量设置为(以及所有其他正常继承的环境变量)。因此,在将环境变量设置为空字符串(意味着没有字段分隔符)的情况下运行命令。varname=value command
varname
value
IFS= read -r -d $'\0'
read -r -d $'\0'
IFS
由于只要它成功读取输入并且没有遇到文件结尾就read
返回成功(即设置$?
为),因此总体效果是循环一组 NUL 分隔的记录(保存在变量中)。0
REPLY
while 语句不需要设置 $ 的 'test' 或 [ ] 或 [[ ]] 表达式吗?为 1 还是 0?
test
and [ ... ]
and[[ ... ]]
实际上不是表达式,而是命令。在 Bash 中,每个命令都返回成功(设置$?
为0
)或失败(设置$?
为非零值,通常是1
)。
(顺便说一下,正如上面评论中的nosid 所指出的那样,-d $'\0'
相当于.Bash-d ''
变量在内部表示为 C 样式/NUL 终止的字符串,因此您不能真正在字符串中包含 NUL;例如,echo $'a\0b'
只打印a
. )
我不明白这行shell脚本。while 语句不需要设置 $ 的 'test' 或 [ ] 或 [[ ]] 表达式吗?为 1 还是 0?[声明]如何做到这一点?
每个人都在回答关于-d
andIFS=
参数的问题,但没有人回答你关于test
and的问题[[..]]
。
所有标准 Unix 命令将在成功时返回零值,在退出时返回非零值。while
and语句使用该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
and命令对此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 存在或哎呀,它不见了!取决于目录中是否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 命令所做的只是在真实测试中返回零,在错误测试中返回非零值。这允许您在和语句中使用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
命令。
代码说明:
IFS=
将 IFS 设置为 null(输入字段分隔符)read
使用以下选项读取当前行的命令:-r
: 不允许反斜杠转义任何字符-d
继续直到读取 DELIM 的第一个字符,而不是换行$'\0'
零字节(ASCII NUL 字符)看
help read
不,test
命令和[[ ...]]
表达式只是提供退出状态(唯一while
关心的事情)的构造,它反映了它包含的条件表达式的真实性。
例如,如果值为,则退出状态[[ $foo = bar ]]
为 0(成功),否则为非零存在状态(具体为 1)。$foo
bar
while
只要while
关键字后面的命令的退出状态为 0,循环就会执行其主体。在此代码中,只要read
它可以从其输入中读取某些内容,则退出状态为 0。