簡體   English   中英

使用 AWK/SED/GREP 打印兩個模式(可能不是成對的)之間的所有行

[英]Print all lines between two patterns (which may not be pairs) with AWK/SED/GREP

我知道這個問題有多個實例,例如打印兩個模式之間的所有行,排他性,僅第一個實例(在 sed、AWK 或 Perl 中)但我的問題是如果這兩個模式可能不配對 - 例如

給定輸入

PATTERN1
bbb
ccc
ddd
eee
fff
PATTERN1
ggg
hhh
iii
PATTERN2
jjj
PATTERN2
kkk

我希望最短范圍作為輸出:

ggg
hhh
iii

這可能嗎?

您能否僅在 GNU awk嘗試根據您顯示的示例進行跟蹤、編寫和測試。

awk '
/PATTERN1/ && found1 && !found2{
  found1=found2=val=""
}
/PATTERN1/{
  found1=1
  next
}
/PATTERN2/{
  found2=1
  if(found1){
    print val
  }
  found1=found2=val=""
  next
}
{
  val=(val?val ORS:"")$0
}
' Input_file

給定樣本的輸出將是:

ggg
hhh
iii

說明:為以上添加詳細說明。

awk '                              ##Starting awk program from here.
/PATTERN1/ && found1 && !found2{   ##Checking if PATTERN1 in current line and found1 is SET and found2 is NOT SET then do following.
  found1=found2=val=""             ##Nullifying found1, found2 and val variables here.
}
/PATTERN1/{                        ##Checking condition if PATTERN1 is found then do following.
  found1=1                         ##Setting found1 here for flagging.
  next                             ##next will skip all further statements from here.
}
/PATTERN2/{                        ##Checking condition if PATTERN2 is found then do following.
  found2=1                         ##Setting found2 here for flagging.
  if(found1){                      ##Checking condition if found1 is SET then do following.
    print val                      ##Printing val here.
  }
  found1=found2=val=""             ##Nullifying found1, found2 and val here.
  next                             ##next will skip all further statements from here.
}
{
  val=(val?val ORS:"")$0           ##Creating val which has current line value and keep appending it with new line.
}
' Input_file                       ##Mentioning Input_file name here.

awk ,你可以通過保存做PATTERN..每一次比較一個PATTERN..遇到。 在兩者之間,您將元素保存在一個數組中,當您有兩個不匹配的模式時——您輸出數組的內容。 否則你清空數組並重置你的計數器,例如

awk '! /PATTERN/ {
        a[++n]=$0
    }
    /PATTERN/ {
        if ($0 != lastptrn)
            for (i=1; i<=n; i++)
                print a[i]
        delete a
        n=0
        lastptrn=$0
    }
' file

輸出

ggg
hhh
iii

如果Perl恰好是您的選擇,請您嘗試:

perl -0777 -ne '/.*PATTERN1\n(.*?)PATTERN2/s && print $1' input

結果:

ggg
hhh
iii
  • -0777選項告訴Perl一次-0777所有行。
  • 正則表達式的s選項告訴Perl在元字符中包含換行符. .
  • .*PATTERN1\\n位置直到最后一個PATTERN1結束。
  • (.*?)指定最短匹配並為匹配的行分配$1

其他:

$ awk '
/PATTERN1/ {                # at starting pattern
    f=1                     # flag up
    b=""                    # reset buffer
    next                    # to exclude the start pattern
}
/PATTERN2/ {                # at ending pattern
    print b                 # output buffer
    exit                    # no need to continue to the end
}
f {                         # when flag up
    b=b (b==""?"":ORS) $0   # buffer records
}' file

要包括開始和結束標記,請刪除next並在/PATTERN2/ {...}之前移動f {...} /PATTERN2/ {...}

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

sed -n '/PATTERN2/{g;/PATTERN1/{s/[^\n]*\n//p;q}};H;/PATTERN1/h' file

概述:將行從PATTERN1到但不包括PATTERN2復制到保留空間中,然后打印保留空間減去第一行。

處理:將所有行附加到保持空間,當匹配時用PATTERN1的內容替換保持空間。

PATTERN2匹配時,用保留空間覆蓋模式空間,如果模式空間包含PATTERN1 ,則刪除第一行,打印模式空間的內容並退出。

暫無
暫無

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

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