2017-02-20 71 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」中,您可以對每個組執行任何處理。在這種情況下,我只是將它們打印出來,但應該很容易修改它以執行任何您想要的操作。