簡體   English   中英

提取模式之間的內容

[英]extract content between patterns

在 SUSE Linux 上,我想從文本文件中找到 BEGIN 字符串和 END 字符串之間的完整部分。 我想過使用 sed 或 awk。

或者,我想在另一次運行中搜索下一次出現。

  • 它應該成為 bash 腳本的一部分
  • 結果應寫入文件

我的挑戰是:

  • BEGIN 字符串在 END 字符串出現之前的開頭出現多次
  • BEGIN 字符串有時在同一行之前有其他字符
  • END 字符串有時在同一行后面有其他字符

例子

something before ----BEGIN
first paragraph
Text Text Text
Text Text Text
Text Text Text
no ending pattern

something before ----BEGIN
second paragraph
Text Text Text
Text Text Text
Text Text Text
END---- some more text

no beginning pattern
Text Text Text
Text Text Text
END---- some more text

something before ----BEGIN
third paragraph
Text Text Text
Text Text Text
Text Text Text
no ending pattern

something before ----BEGIN
fourth paragraph
Text Text Text
Text Text Text
Text Text Text
END---- some more text

Text Text Text

我期待這樣的事情:

----BEGIN
second paragraph
Text Text Text
Text Text Text
Text Text Text
END----

在另一次運行中,我想找到下一個完整的部分:

----BEGIN
fourth paragraph
Text Text Text
Text Text Text
Text Text Text
END----

在論壇中,我已經可以找到這樣的東西:

tac < file.txt | sed  '/END-----/,$!d;/-----BEGIN/q' | tac

但它只查找最后一次出現的字符,並不會剪切開頭和結尾的字符。

不幸的是,我在使用 sed/awk 或 regex 方面沒有經驗。 如果您能給我一些指導,我將不勝感激!

干杯,erd

$ cat tst.awk
BEGIN { beg="----BEGIN"; end="END----" }
sub(".*"beg,beg) { inBlock=1; buf="" }
inBlock {
    buf = buf $0 ORS
    if ( sub(end".*",end,buf) ) {
        print buf ORS
        inBlock=0
    }
}

$ awk -f tst.awk file
----BEGIN
second paragraph
Text Text Text
Text Text Text
Text Text Text
END----

----BEGIN
fourth paragraph
Text Text Text
Text Text Text
Text Text Text
END----

這是否可行尚不完全清楚,但根據示例輸入做出幾個假設,您可以嘗試:

awk '/BEGIN/ && /END/' RS= ORS='\n\n' input

這將過濾掉您想要的記錄(同樣,我正在根據輸入樣本對您實際想要的內容進行假設),然后您可以輕松地使用第二個 awk 選擇記錄。 例如,要獲取第 n 條記錄,您可以執行以下操作:

N=2; awk '/BEGIN/ && /END/' RS= ORS='\n\n' input  | awk 'NR==n' n=$N RS=

把它放在一個循環中,用 N 作為循環計數器,你就有了你(似乎)想要的一切。

BEGINEND之間的緩沖區行在BEGIN發生時丟棄緩沖區,並在到達END時打印緩沖區。 請注意,這假設在----BEGIN之前和END----之后總是有一個空格。

awk '/BEGIN$/,/^END/ {
  if(/BEGIN$/) {
    buf=$NF
  }
  else if(/^END/) {
    print buf
    print $1
  }
  else {
    buf=(buf ORS $0)
  }
}' file

看起來 BEGIN/END 標記不可靠,您依賴於記錄之間的空行, awk記錄模式支持這種情況。

$ awk -v n=2 -v RS= 'BEGIN {b="BEGIN"; e="END"; h="----"; s=".*"} 
                     NR==n {sub(s h b, h b); 
                            sub(e h s, e h); 
                            print}' file

----BEGIN
second paragraph
Text Text Text
Text Text Text
Text Text Text
END----

這可能對你有用(GNU sed &bash):

b='----BEGIN' e='END----' n=1
sed -En '/'$b'/{:a;N;/'$e'/!ba;x;s/^/x/;/^x{'$n'}$/!{x;b};x;s/.*('$b'.*'$e').*/\1/p}' file

這會收集----BEGINEND----之間的行,然后使用貪婪在結果字符串中找到最后一次出現的----BEGIN 作為結果呈現的結果字符串的數量可以由n變量確定(在上面的示例中,它是第一個)。 第二個示例解決方案如下:

b='----BEGIN' e='END----' n=2
sed -En '/'$b'/{:a;N;/'$e'/!ba;x;s/^/x/;/^x{'$n'}$/!{x;b};x;s/.*('$b'.*'$e').*/\1/p}' file

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM