2017-02-20 61 views
1

我有一个多输出,就像这样:解析多使用awk

foo: some text 
    goes here 
    and here 
    and here 
bar: more text 
    goes here 
    and here 
xyz: and more... 
    and more... 
    and more... 

文本的格式是完全如下所示。我感兴趣的文本的“分组/分节”从该行开始之后开始,并且在下一个文本从行开始处开始之前结束。

在此示例中,群组将为foo,并且在bar之前的所有文本。然后barxyz之前的所有文本。最后,xyz直到结束。

+4

没有描述输出应该如何显示,在代码块中显示。 – Kent

+2

而某种尝试会很好。 – grail

+0

如果没有预期的输出,就很难理解这个问题 – anubhava

回答

2

输入

$ cat file 
foo: some text 
    goes here 
    and here 
    and here 
bar: more text 
    goes here 
    and here 
xyz: and more... 
    and more... 
    and more... 

输出

$ awk '/:/{f=/^foo/}f' file 
foo: some text 
    goes here 
    and here 
    and here 

柜面,如果你想跳过线匹配然后

$ awk '/:/{f=/^foo/;next}f' file 
    goes here 
    and here 
    and here 

甚至

# Just modify variable search value 
# 1st approach 
$ awk -v search="foo" '/:/{f=$0~"^"search}f' file 
foo: some text 
    goes here 
    and here 
    and here 

# 2nd approach 
$ awk -v search="foo" '/:/{f=$0~"^"search;next}f' file 
    goes here 
    and here 
    and here 
+1

如果你可以建议把'foo'作为'-v'中的一个变量来传递,那么他可以相应地使用它。 – Inian

+0

@Inian:我确定现在编辑 –

0

如果我解释你的问题正确的要简单地删除空格,并把foo在另一条线路比:之后的部分。这awk脚本会做到这一点:

awk 'BEGIN{RS="[:\n]"}{$1=$1}1' file 

输出:

foo 
some text 
goes here 
and here 
and here 
bar 
more text 
goes here 
and here 
xyz 
and more... 
and more... 
and more... 

说明:

  • RS="[:\n]说,电线应该在:\n
  • $1=$1拆分重新处理行到$0(删除开头的空格线)
  • 1说,每行应与“默认操作”,这是print $0
0

正如其他人所说,你没有指定你想一旦你的数据做什么处理解析它。

如果你只是想提取一个特定的块,来自Akshay Hegde的答案应该可以正常工作。

如果你想使用更多的awk功能来处理每条记录,比如以某种方式转换输出(例如将线条连接在一起等),你可能需要一些不同的东西。

有几个相当简单的方法可以做到这一点,但我认为最好的方法可能是更改记录分隔符。

使用正则表达式作为记录分隔符的能力是一个gawk扩展,但是如果您在Linux上,则可能使用gawk。

这是徒劳无功的程序文件“prog.awk”的内容:

function process_group(name, body) { 
    print "Got group with name '" name "'"; 
    print body; 
} 

BEGIN { 
    RS="(\n|^)\\S+:" 
    PREV="" 
} 

{ 
    if (PREV!="") { 
     process_group(gensub(/\n?(\S+):/, "\\1", "", PREV), $0); 
    } 
    PREV=RT 
} 

您可以运行此使用

gawk -f prog.awk input.txt 

或者你可以把整个事情的GAWK命令 - 行,但如果格式良好,则更容易阅读。

这个想法是,它每次看到记录分隔符时,都会为您提供自上次记录分隔符或文件开头以来的内容。这意味着它第一次看到记录分隔符时,它会调用带有记录分隔符“foo:”的底部块和一个空体,第二次它看到记录分隔符时,它将调用带有“bar:”的块并将内容“foo:”和“bar:”等。

这意味着每个块对应的记录分隔符是前一个,而不是当前的。通过跟踪“PREV”变量中的前一个记录分隔符,这很容易处理。

因此,BEGIN块设置记录分隔符RS,并将PREV初始化为空。

为每个由RS定界的记录调用底部的块,并在文件末尾再次调用。

如果“PREV”不为空,它将使用当前正文数据和前一个记录分隔符(通过使用gensub从PREV中删除不感兴趣的位)调用“process_group”函数。然后它将当前匹配的记录分隔符(RT)分配给PREV以供下次使用。

在“process_group”中,您可以对每个组执行任何处理。在这种情况下,我只是将它们打印出来,但应该很容易修改它以执行任何您想要的操作。