使用awk,sed或grep获取文本文件的子部分

时间:2012-07-25 18:16:18

标签: bash sed awk grep

我担心我不是列出的三种工具中的任何一位的专家,所以我问你们所有人。

我有一个大文本文件,可以分成多个部分,每个部分都有标题ABC和页脚&&。典型的文件如下所示:

ABC

...

<ID>
123

...

&&

ABC

...

<ID>
124

...

&&

我需要根据给定的ID检索一个部分,例如ID=123,我希望输出为:

ABC

<ID>
123

&&

ABC <ID>之间以及123&&之间存在随机数据。实际的ID123是可变的。

我相信做awk '/ABC/,/\&\&/'可以找到每个小节,但我不知道如何获得对应于正确ID的小节。提前感谢您的帮助。

编辑:澄清了问题和示例输入。

4 个答案:

答案 0 :(得分:1)

此解决方案假设您的输入文件仅由ABC ... <ID> ... &&个部分组成,可能用空行分隔。

USAGE: awk -f foo.awk ID=123 input_file

<强> foo.awk:

#!/usr/bin/awk -f
BEGIN {
    RS = "\n&&\n";
    ORS = RS;
}

match($0, "<ID>\n" ID "\n") {
    sub(/^\n/,"",$0);
    print $0;
}

如果/usr/bin/awk与您的awk匹配并且您创建了foo.awk可执行文件,则可以直接调用它:./foo.awk ID=123 input_file

此代码将您的输入拆分为单行上每个&&的记录 然后它搜索记录

<ID>
your_id

并在找到匹配项时打印它。

sub(/^\n/,"",$0);只是消除了各个部分之间的空白行。

您也可以在一行中使用此功能:

 awk 'BEGIN{ID=124;RS="\n&&\n";ORS=RS};match($0, "<ID>\n" ID "\n") {sub(/^\n/,"",$0);print $0;}' input_file

答案 1 :(得分:0)

在sed中你可以这样做:

sed -i ' /ABC/,/&&/ !{d} ' FILE

这将保留ABC和&amp;&amp;。

之间的所有背景

答案 2 :(得分:0)

用法:awk -v id=123 -f foo.awk foo.txt

<强> foo.awk

$0=="ABC",$0=="&&"{
    # store everything in data
    # ternary operation to avoid leading "\n"
    data=data?(data "\n" $0):$0
}


id_flag {
    # this is a string after "<ID>"
    if (id==$1) { 
       print_flag = 1
    }
    id_flag = 0
}

$0=="<ID>"{
    # prepare to read id
    id_flag = 1
}

$0=="&&"{
    if (print_flag) {
      print data
      print_flag = 0
    }
    data = ""
}

答案 3 :(得分:0)

这可能适合你(GNU sed):

id=123
sed '/^ABC/,/^&&/{/^ABC/{h;d};H;/^&&/!d;g;/<ID>\n'"$id"'/p};d' file

另一种方法:

sed ':a;$bb;N;/^ABC/!D;/&&$/!ba;:b;/^ABC.*<ID>\n'"$id"'.*&&$/p;d' file