寻找不同线条的模式

时间:2017-11-14 09:25:23

标签: awk sed grep

我有一个这样的文件(test.txt):

abc
12
34
def
56
abc
ghi
78
def
90

我想搜索被“abc \ nghi”和“def”包围的78。目前,我知道我可以这样做:

cat test.txt | awk '/abc/,/def/' | awk '/ghi/,'/def/'

还有更好的方法吗?

5 个答案:

答案 0 :(得分:2)

一种方法是使用标志

$ awk '/ghi/ && p~/abc/{f=1} f; /def/{f=0} {p=$0}' test.txt
ghi
78
def
  • {p=$0}这将保存输入行以供将来使用
  • /ghi/ && p~/abc/{f=1}设置标记,如果当前行包含ghi且前一行包含abc
  • 只要设置了标志
  • f;打印输入记录
  • 如果行包含/def/{f=0} ,则
  • def清除该标记


如果你只想要这两个边界之间的界线

$ awk '/ghi/ && p~/abc/{f=1; next} /def/{f=0} f; {p=$0}' ip.txt
78
$ awk '/12/ && p~/abc/{f=1; next} /def/{f=0} f; {p=$0}' ip.txt
34

另见How to select lines between two patterns?

答案 1 :(得分:0)

这不是很干净,但您可以将记录分隔符重新定义为正则表达式abc\nghi\n|\ndef。然而,这会创建多个记录,您需要跟踪哪些记录在正确的记录之间。使用awk,您可以使用RT检查找到哪个RS。

awk 'BEGIN{RS="abc\nghi\n|\ndef"}
     (RT~/abc/){s=1}
     (s==1)&&(RT~/def/){print $0}
     {s=0}' file

这样做:

  • RS设置为abc\nghi\n\ndef
  • 检查是否找到了记录,如果RT包含abc您找到了第一个记录。
  • 如果您找到第一个,RT包含def,则打印。

答案 2 :(得分:0)

grep替代

$ grep -Pazo '(?s)(?<=abc\nghi)(.*)(?=def)' file

但我认为awk会更好

答案 3 :(得分:0)

你可以用sed做到这一点。它并不理想,因为它实际上并不理解记录,但它可能适合你...

        // use properties to open the datasource for work
        System.out.println("Opening database connection.");
        logger.info("Opening database");
        String dbDriver = dbProps.get("dbDriver");
        String dbURL = dbProps.get("dbURL");
        String username = dbProps.get("username");
        String password = dbProps.get("password");

        Base.open(dbDriver, dbURL, username, password);
        logger.info("Database successfully opened.");

这是基本上发生的事情:

  • sed -Ene 'H;${x;s/.*\nabc\nghi\n([0-9]+)\ndef\n.*/\1/;p;}' input.txt - 将当前行追加到sed的“保留空间”
  • H - 指定一旦我们到达文件末尾就会运行的一系列命令的开始
  • ${ - 使用模式空间交换保留空间,以便将来的替换可以使用x
  • 存储的内容
  • H - 分析模式空间(现在是多行),捕获问题中指定的数据,用括号表达式替换整个模式空间......
  • s/../../ - 打印结果。

这里的一个重要因素是正则表达式是ERE,因此p选项很重要。如果您的sed版本使用其他选项来启用对ERE的支持,请改用该选项。

另一个考虑因素是上面的正则表达式假设是Unix风格的行结尾。如果您尝试处理在DOS或Windows上生成的文本文件,则正则表达式可能需要稍微不同。

答案 4 :(得分:-1)

awk 解决方案:

awk '/ghi/ && r=="abc"{ f=1; n=NR+1 }f && NR==n{ v=$0 }v && NR==n+1{ print v }{ r=$0 }' file

输出:

78

奖金 GNU awk方法:

awk -v RS= 'match($0,/\nabc\nghi\n(.+)\ndef/,a){ print a[1] }' file