2012-07-25 115 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