2017-02-09 37 views
1

我有一個文件格式如下。Shell腳本 - 搜索多行模式並刪除記錄如果匹配

I PRP B-PRP 
am VBP B-VBP 
a DT B-DT 
happy JJ B-JJ 
soul NN B-NN 

I PRP B-PRP 
am VBP B-VBP 
a DT B-DT 
sad JJ B-JJ 
soul NN B-NN 

每條記錄​​都由空行分隔。每行有3個字段。

如果有輸入我是一個快樂的靈魂我想在這個文件中搜索並刪除記錄,如果它存在。在這個例子中,記錄一個將從文件中刪除。由於這句話是以多行的形式傳播的,我無法弄清楚如何做到這一點。我試過sed,awk,grep。似乎沒有任何工作。基本上,我不知道如何給這些命令的模式。

sed -e '/I/,/soul/!d' filename 

大多數的意見是像上述類型開始隨後端圖案圖案。但這不適用於我的情況。

如何解決這個問題?

回答

3

如果有輸入我是一個快樂的靈魂我想在這個文件中搜索並刪除記錄,如果它存在。

您可以使用此awk命令:

awk -v RS= '!/^I .*\nam .*\nhappy .*\nsoul /' file 

I PRP B-PRP 
am VBP B-VBP 
a DT B-DT 
sad JJ B-JJ 
soul NN B-NN 
+0

它的工作。謝謝。 – BBHeeMAA

+0

如何將'regex'作爲shell變量傳遞?那可能嗎? – BBHeeMAA

+0

是的。這是可能的。 – BBHeeMAA

2

使用AWK一個可以設置RS(記錄分隔符)落空,對空行分割記錄:

$ awk '/I.*am.*happy.*soul/' RS= input.txt 
I PRP B-PRP 
am VBP B-VBP 
a DT B-DT 
happy JJ B-JJ 
soul NN B-NN 

.*在兩個正則表達式元字符,.指任何字符,而*意味着零次或多次。

我不確定.是否與換行符相符。

+0

那豈不是失敗'III MAM ahappyp asould',然後再次我不知道這是否重要? –

+1

@JamesBrown這是真的,人們可以使用單詞邊界來避免這種情況。但我不確定對每種語法的支持,即:GNU awk支持'\ <' and '\>',但我不認爲POSIX awk可以。 – andlrc

1

確切的方法(除了順序,這將需要a[$i]=i... ("am" in a) && a["I"]<a["am"] && ...):

$ awk -v RS= ' 
{ 
    delete a; 
    for(i=1;i<=NF;i++) # iterate every word 
     a[$i]   # and store it 
} 
("I" in a) && ("am" in a) && ("a" in a) && ("happy" in a) && ("soul" in a) {next} 1 
' test 
I PRP B-PRP 
am VBP B-VBP 
a DT B-DT 
happy JJ B-JJ 
soul NN B-NN 

編輯:版本,測試確切的單詞匹配和在塊的話(當然,在這種情況下記錄),並接受搜索詞作爲參數順序(見s代碼):

$ awk -v ORS="\n\n" -v RS= -v s="I am a happy soul" ' 
BEGIN { 
    n=split(s,a)    # split the searched sentance to a hash 
} 
{ 
    delete b;     # delete b or block words 
    for(i=1;i<=NF;i++)  # iterate thru all words 
     b[$i]=i;    # give each word ad order (* see below) 
    for(i=1;i<=(n-1);i++)  # for each word in a see the order of block words 
     if(b[a[i]]>b[a[i+1]]) # printing at first mismatch 
      print $0 
}' test 

(*)我沒有測試,如果發生了什麼一個想要的單詞在單詞塊中存在兩次。最後的位置仍然是這個詞,所以去圖...

+0

但是如何從文件中刪除該記錄?我試過這個代碼,但它沒有刪除。 – BBHeeMAA

+0

@BBHeeMAA哦,我的壞。它恰恰相反。現在修復。 –

+0

如何在打印輸出時在記錄之間添加新行? – BBHeeMAA

1

這可能爲你工作(GNU SED):

sed ':a;N;/^$/M!ba;/I.*am.*a.*happy.*soul/d' file 

閱讀多行進入模式空間,在遇到一個空行,符合要求的字符串,如果需要將其刪除。

更防彈解決方案可能是:

sed ':a;$!{N;/^\s*$/M!ba};/\<I\>.*\<am\>.*\<a\>.*\<happy\>.*\<soul\>/d' file