我知道这个问题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
边界条件fixedValue
和outlet
边界条件inletOutlet
。
如果我使用cat BCFile | grep "type" | awk '{printf $2}' | tr -d ";"
,则无法多次使用关键字type
。
如果我使用awk -v RS='}' '/inlet/ { print $4 }' BCFile
,它也无法使用,因为关键字inlet
也会多次出现。
我需要一种方法来查找首先搜索关键字inlet
的模式,然后搜索最近的 {
和}
。
任何人都知道如何巧妙地做到这一点?
答案 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
如果您缩小“入口”与下一个“}”或“出口”之间的“类型”搜索范围,以及下一个“}”,这样可以使整个练习更轻松。