1

我知道这个问题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然后搜索最接近 {的和}.

有谁知道如何巧妙地做到这一点?

4

3 回答 3

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后跟除 a 之外的任何字符的单词(因此您在文件中的第一个之后而不是最后一个}之前停止),然后是后面跟着空格的单词。( ) 之后的字母数字字符串是您要打印的单词,因此请记住它,然后将整个记录替换为保存在.}inlet}type\w+\\1

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

于 2013-04-05T13:45:22.477 回答
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";
于 2013-04-05T03:31:17.897 回答
1

这可能对您有用(GNU sed):

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

如果您在“入口”和下一个“}”或“出口”和下一个“}”之间缩小“类型”的搜索范围,这会使整个练习变得更容易。

于 2013-04-05T07:41:49.723 回答