sed 可以对空文件执行命令(退出命令)

sed 可以对空文件执行命令(退出命令)

我有一个 shell 脚本,我想在其中验证文件的内容。

预期的内容应该有一个特定的第一行,例如^MYFIRSTROW不能为空。

所以我使用 GNU 编写了这个检查sed

#!/bin/bash

# "1q1": return 1 on input line 1. Only reached if the pattern did not match.
if sed -rn '/^MYFIRSTROW/q0; 1q1' myfile; then
   # ...
fi

但我在空输入上进行了测试,然后sed返回 0 而不是 1:

echo -ne '' | sed -rn '/^MYFIRSTROW/q0; 1q1'; echo $?
# 0

另外,在这种情况下我没有找到使用地址“0”的方法。

有没有一种方法可以在 GNU sed 中用一个命令来实现它?

注意:替代解决方案

我主要想回答是否可以在空输入上执行 sed 命令以及如何执行,但欢迎对我的 shell 脚本提出优雅的建议:

  • 我很慢,但我刚刚意识到这if [ -s "myfile" ] && sed ...可以完成工作。

  • 我可以想象使用while read < myfile但似乎很麻烦的解决方案。

  • 我在 中遇到了相反的问题awk,其中 END 块始终被执行,因此此代码始终返回 1:

    awk 'NR==1 && /^MYPATTERN/ {exit 0}END{exit 1}' myfile
    

PS:抱歉,我的问题可能看起来太像代码高尔夫请求,但我只是想在我的脚本中进行简洁高效的文件内容检查。

答案1

主要答案是:否。sed对每一行执行其脚本,因此如果没有行,则无法执行任何命令。

解决方法:让你的 shell 立即添加一行:

sed -n '/^MYPATTERN/q;$q1;2q2' <(echo) yourfile

假装<(echo)是一个只有一个空行的文件,因此sed将始终执行它的脚本。如果yourfile为空,则第一行也是最后一行,因此$q1将以状态 1 退出。

否则脚本将在 的第一行执行yourfile。如果匹配,则退出并返回状态码 0。

如果不匹配,则sed存在,状态为 2。请注意,添加的行使文件的第一行显示为第 2 行sed

感谢 Stéphane Chazelas 提示如何在不支持 ksh 样式进程替换的情况下为 shell 实现相同的功能:

echo|sed -n '/^MYPATTERN/q;$q1;2q2' - yourfile

as-参数代表 stdin,它是从 管道传输的空行echo

答案2

使用 AWK,您可以设置一个变量来告诉END块要设置哪个退出代码。在这里,滥用了ok如果没有明确分配则为零的事实。 (或者,添加BEGIN { ok=0 }明确的内容。)

awk 'NR==1 && /^MYPATTERN/ {ok=1; exit} NR==2 {exit} END {exit !ok}' myfile

这是故意的,而且很可能是打高尔夫球的。因为我们只在第一行寻找模式。


我不知道如何在 sed 中以简单的方式做到这一点。尽管您可以颠倒过来,如果MYPATTERN看到则以1 退出,并依赖于空文件以 0 退出。然后你需要反转周围的感觉if

if ! sed -Ene '/^MYPATTERN/q1; 1q0' myfile; then
    echo "MYPATTERN seen..."
fi

尽管这会转到if(和 print MYPATTERN seen...) 的主分支,即使 sed 返回实际错误,例如无法读取myfile.

相关内容