如何找到多线模式匹配(它们必须是第一次匹配)?

时间:2013-04-05 02:57:52

标签: regex shell sed awk

我知道这个问题How to find patterns across multiple lines using grep?但我认为我的问题更复杂。所以我需要帮助。

我有一个字典文件BCFile

boundary
{
    inlet
    {
        type            fixedValue;
        value           uniform (5 0 0);
    }

    outlet
    {
        type            inletOutlet;
        inletValue      $internalField;
        value           $internalField;
    }

    ....
}

我正在编写一个脚本,以便打印出inlet边界条件fixedValueoutlet边界条件inletOutlet

如果我使用cat BCFile | grep "type" | awk '{printf $2}' | tr -d ";",则无法多次使用关键字type

如果我使用awk -v RS='}' '/inlet/ { print $4 }' BCFile,它也无法使用,因为关键字inlet也会多次出现。

我需要一种方法来查找首先搜索关键字inlet的模式,然后搜索最近的 {}

任何人都知道如何巧妙地做到这一点?

3 个答案:

答案 0 :(得分:2)

由于您没有为您发布的输入提供预期输出,我们只是猜测您想要输出的内容,但在GNU awk中如何:

$ cat tst.awk
BEGIN{ RS="\0" }
{
   print "inlet:",  gensub(/.*\yinlet\y[^}]*type\s+(\w+).*/,"\\1","")
   print "outlet:", gensub(/.*\youtlet\y[^}]*type\s+(\w+).*/,"\\1","")
}
$ gawk -f tst.awk file
inlet: fixedValue
outlet: inletOutlet

说明:

RS="\0"

=将Record Separator设置为Null字符串,以便awk将整个文件作为单个记录读取。

gensub(/.*\yinlet\y[^}]*type\s+(\w+).*/,"\\1","")

=查找单词inlet,后跟除}以外的任何字符(因此您在}之后的第一个inlet之前停止而不是最后}在文件中)然后单词type后跟空格。之后的字母数字字符串(\w+)是您要打印的单词,请记住它,然后将整个记录替换为\\1中保存的字符串。

设置RS="\0"gensub()都是特定的gawk。

答案 1 :(得分:1)

你能用perl吗?

#!/usr/bin/env perl

use strict;
use warnings;

my $filename = $ARGV[0];

open(my $f, '<', $filename) or die "Unable to open $filename: $!\n";
my $string = do { local($/); <$f> };
close($f);

$string =~ /(inlet).*type\s*(\w+).*(outlet).*type\s*(\w+)/s;
print "$1: $2\n$3: $4\n";

答案 2 :(得分:1)

这可能适合你(GNU sed):

sed -rn '/^\s*(inlet|outlet)/,/^\s*}/!b;/type/s/.*\s(\S+);.*/\1/p' file

如果您缩小“入口”与下一个“}”或“出口”之间的“类型”搜索范围,以及下一个“}”,这样可以使整个练习更轻松。

相关问题