2012-07-25 121 views
1

恐怕我不是上述三种工具中的任何一个的专家,所以我要求大家。使用awk,sed或grep获取文本文件的子部分

我有一个大的文本文件,可以分成多个部分,每个部分的标题为ABC和页脚&&。一个典型的文件看起来像这样:

ABC 

... 

<ID> 
123 

... 

&& 

ABC 

... 

<ID> 
124 

... 

&& 

我需要检索基于给定ID一个部分,例如,如果ID=123,我想输出是:

ABC 

<ID> 
123 

&& 

哪里有是ABC<ID>之间,以及123&&之间的随机数据。实际的ID,123是可变的。

我相信做awk '/ABC/,/\&\&/'工作在找到每个小节,但我不知道如何得到正确的ID对应的小节。预先感谢您的帮助。

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

回答

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 
+0

与@slitvinov的解决方案类似,如果文本文件中只有一个以' ABC'并以'&&'结尾。典型的文本文件将包含多个部分,但每个部分都有不同的ID。 – Alex 2012-07-27 21:00:29

+0

@Alex这应该只检索包含输入ID的部分,而不管多个部分。 – potong 2012-07-28 06:09:03

0

在sed你可以这样做:

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

这将让美国广播公司和& &之间的所有内容。

+0

对不起,歧义。我的意图是用标题“ABC”和页脚“&&”以及正确的ID来检索一个小节,而不是插入ID行。文本文件的每个子部分都有不同的ID。 – Alex 2012-07-27 20:25:27

+0

谢谢。现在很清楚,并解决了它。 – alinsoar 2012-07-27 20:31:59

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 = "" 
} 
+0

我觉得我的问题有点含糊。我有一个普通的文本文件将有多个部分,每个部分以'ABC'开始,以'$$$$'结尾。我相信这个解决方案只适用于具有如上所述的单个部分的文本文件。 – Alex 2012-07-27 20:47:07

+0

以'&&'结尾。 – Alex 2012-07-27 20:53:57

1

此解决方案假定您的输入文件全部由ABC ... <ID> ... &&部分,可能由空行分隔。

用法: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 
+0

酷解决方案!我将使它更地道,并添加正则表达式来处理' \ N123 \ N &&':'BEGIN { ORS = RS = “\ N && \ n” 个 } 比赛($ 0, “ \ n” ID“( \ n \ n“,”) print } – slitvinov 2012-07-29 17:12:34

相关问题