awk 或 sed 命令在特定行匹配正则表达式,如果成功则退出真,否则为假

Oth*_*eus 6 gnu-screen sed awk text-processing puppet

我需要确定文件是否在某一行包含某个正则表达式,如果找到则返回 true(退出 0),否则返回 false。也许我想得太多了,但事实证明我的尝试有点笨拙。我有一个解决方案,但我正在寻找我没有想到的其他解决方案。我可以使用 perl,但我希望尽可能保持这种“轻量级”,因为它在 puppet 执行周期中运行。

这个问题很常见:​​在 RHEL6 中,screen 的打包方式将终端宽度限制为 80 个字符,除非您取消注释 132 行。此命令检查该行是否已修复:

 awk 'NR==132 && /^#termcapinfo[[:space:]]*xterm Z0=/ {x=1;nextfile} END {exit 1-x}' /etc/screenrc
Run Code Online (Sandbox Code Playgroud)

注意:如果文件少于 132 行,它必须以 false 退出。

我认为sed在这里会有帮助,但显然你必须做一些奇怪的技巧,比如空替换和分支。尽管如此,我还是希望看到一个 sed 解决方案来学习。也许还有一些我忽略的东西。

编辑 1:添加nextfile到我的 awk 解决方案中

编辑 2:基准 编辑 3:不同的主机(空闲)。编辑 4:错误地将 Gile 的 awk 时间用于优化运行。编辑 5:新长凳

基准

首先,请注意:wc -l /etc/screenrc216。不存在线路时的 50k 次迭代,以挂墙时间衡量:

  • 空操作:0.545s
  • 我原来的 awk 解决方案:58.417
  • 我编辑过的 awk 解决方案(使用 nextfile):58.364s
  • Giles 的 awk 解决方案:57.578s
  • 优化的 perl 解决方案 90.352s Doh!
  • Sed 132{p;q}|grep -q ... 解决方案:61.259s
  • Cuonglm's tail | head | grep -q: 70.418s 哎哟!
  • Don_chrissti 的head -nX |head -n1|grep -q:116.9 秒 Brrrrp!
  • Terdon 的双 grep 解决方案:65.127s
  • John1024 的 sed 解决方案:45.764s

谢谢约翰,谢谢 sed!老实说,我很惊讶 perl 在这里是一样的。Perl 在启动时加载了一堆共享库,但只要操作系统缓存它们,它就归结为解析器和字节编码器。在遥远的过去(perl 5.2?)我发现它慢了 20%。Perl 比我最初预期的要慢,但由于我的复制/粘贴错误,它似乎更好。

基准测试第 2 部分

有实用价值的最大配置文件是/etc/services. 所以我为这个文件重新运行了这些工作台,要更改的行是文件中的 2/3rds。总行数是 1100,所以我选择了 7220 并相应地修改了正则表达式(这样在一种情况下它会失败,在另一种情况下它会成功;对于工作台它总是失败)。

  • John 的 sed 解决方案:121.4s
  • Christi 的{head;head}|grep解决方案:138.341s
  • Counglm 的tail|head|grep解决方案:77.948s
  • 我的 awk 解决方案:175.5s

Joh*_*024 14

使用 GNU sed:

sed -n '132 {/^#termcapinfo[[:space:]]*xterm Z0=/q}; $q1'
Run Code Online (Sandbox Code Playgroud)

这个怎么运作

  • 132 {/^#termcapinfo[[:space:]]*xterm Z0=/q}

    在第 132 行,检查 regex ^#termcapinfo[[:space:]]*xterm Z0=。如果找到退出,q则默认退出代码为 0。文件的其余部分将被跳过。

  • $q1

    如果我们到达最后一行,$则退出并退出代码 1: q1

效率

由于没有必要读取文件的第 132 行,因此只要我们到达第 132 行或文件末尾(以先发生者为准),此版本就会退出:

sed -n '132 {/^#termcapinfo[[:space:]]*xterm Z0=/q; q1}; $q1'
Run Code Online (Sandbox Code Playgroud)

处理空文件

对于空文件,上面的版本将返回 true。这是因为,如果文件为空,则不执行任何命令并且 sed 以默认退出代码 0 退出。为避免这种情况:

! sed -n '132 {/^#termcapinfo[[:space:]]*xterm Z0=/q1; q}'
Run Code Online (Sandbox Code Playgroud)

这里, sed 命令以代码 0 退出,除非找到所需的字符串,在这种情况下,它以代码 1 退出。 前面的命令!告诉 shell 反转此代码以返回到我们想要的代码。!所有 POSIX shell 都支持该修饰符。此版本甚至适用于空文件。(帽子提示:G-Man)


cuo*_*glm 5

使用 POSIX 工具箱:

tail -n +132 </etc/screenrc | head -n 1 | grep -q pattern
Run Code Online (Sandbox Code Playgroud)