而IFS =读取-r -d $'\ 0'文件...解释

时间:2013-08-13 19:48:32

标签: bash

我不明白这行shell脚本。 while语句是否需要设置$的'test'或[]或[[]]表达式?到1还是0?怎么做

while IFS= read -r -d $'\0'; do ...; done
那样做吗?非常感谢任何理解语法的帮助。

4 个答案:

答案 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? [声明]如何做到这一点?

每个人都在回答-dIFS=参数,但没有人回答您关于test[[..]]的问题。

所有标准Unix命令将在成功时返回零值,在退出时返回非零值。 whileif语句使用该值来确定是否继续循环:

假设您执行以下操作:

$ 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。

ifwhile命令对此进行操作。

进入另一个终端窗口并创建一个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的文件在目录中。

请注意,ifwhile会对命令的 返回退出值 起作用。根本不需要测试。

为什么test[...][[...]]语法为何?

假设您想知道$foo是否等于$bar。这就是test发挥作用的地方。试试这个:

$ foo=42
$ bar=42
$ test "$foo" -eq "$bar"
$ echo $?
0
$ bar=0
$ test "$foo" -eq "$bar"
$ echo $?
1

所有测试命令都会在 true 测试中返回零,在 false 测试中返回非零值。这允许您在testif语句中使用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命令,该命令将返回ifwhile可以使用的零或非零值。

顺便说一下,在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,只要它可以从输入中读取内容。