Bash中的多行模式匹配

5

我有一个类型很长的文件

Processin SCRIPT10 file..
Submitted batch job 1715572
Processin SCRIPT100 file..
Processin SCRIPT1000 file..
Submitted batch job 1715574
Processin SCRIPT10000 file..
Processin SCRIPT10001 file..
Processin SCRIPT10002 file..
Submitted batch job 1715577
Processin SCRIPT10003 file..
Submitted batch job 1715578
Processin SCRIPT10004 file..
Submitted batch job 1715579

我希望找出未提交的工作(脚本名称),这意味着在处理完一行后没有提交批处理作业。

到目前为止,我已经尝试使用以下方法来完成此任务:

pcregrep -M "Processin.*\n.*Processin" execScripts2.log | awk 'NR % 2 == 0'

但是它不能正确处理多个脚本没有被处理的情况。出人意料的是,它只输出SCRIPT1000和SCRIPT10001行。你能给我展示更好的一行代码吗?
理想情况下,输出应该只有下一行没有“Submitted”(或者只有脚本名称)的行,这意味着:
SCRIPT100
SCRIPT10000
SCRIPT10001

感谢您的需求。

你期望的输出是什么? - anubhava
理想情况下是SCRIPT100、SCRIPT10000和SCRIPT10001。它们后面没有“已提交”行。问题已相应地进行了编辑。 - VojtaK
2个回答

3
这个 awk 可以完成这项工作:
awk -v s='Submitted' '$1 != s{if(p != "") print p; p=$2} $1 == s{p=""}' file

SCRIPT100
SCRIPT10000
SCRIPT10001

参考: AWK编程的有效方法


1

如果不使用 awk,您可以编写一个 bash 命令/文件并运行它。如果您对 awk 的了解较少,则此 bash 脚本在需要进一步定制时更有效。

#!/bin/bash


tempText=""
Processing="Processin"

while read line
do
  tempText=$line
  if [[ "$line" == Processin* ]];
  tempText=$line
  then
        read line
        if [[ "$line" != Submitted* ]];
        then
                echo $tempText
                tempText=$line
                while read line
                do
                        if [[ "$line" != Submitted* ]];
                        then
                                echo $tempText
                                tempText=$line
                        else
                                break
                        fi
                done
        fi
  fi

使用./check.sh 文件名来运行。

当前的答案已经很好了。


1
这样做会非常缓慢,并且在处理不同的输入值时会以各种方式失败。不要这样做。阅读“为什么使用shell循环处理文本被认为是不良实践” 以了解其中的一些问题,但并非全部。 - Ed Morton
1
哦,我不知道那个。谢谢! - Basit Anwer
1
我认为这也很有用,因为在使用awk时,过多的“魔法”会损害代码的可读性。 - VojtaK

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接