
早安,這和問題非常相似Grep 從最後一次出現的模式到另一個模式(幾個月前),同時添加更多細節。
我正在嘗試為具有多個重複模式的檔案編寫 UNIX 腳本,然後向我要尋找的模式。 However I do not have 'tac' or 'tail -r' (using the UNIX emulator, MKS Toolkit), and am looking to return the last occurrence of Pattern1 before Pattern2, followed by the data in between Pattern1 and Pattern2, and then Pattern2也.本例中的模式為「條件 1」和「條件 2」:
輸出:
...
Condition 1: A
data1
Condition 1: B
data2
Condition 2: C
data3
Condition 1: D
data4
Condition 1: E
data5
Condition 2: F
...
我想編寫一個 awk (或 sed,但認為 awk 將是正確的工具)腳本來返回:
Condition 1: B
data2
Condition 2: C
Condition 1: E
data5
Condition 2: F
我認為這是下面一行的某種形式,但我無法正確理解語法:
awk '/Condition 1/ {acc = $0;} /,/Condition 2/ {print ?}' output.out
使用“/,/”似乎是我遇到困難的地方。想知道是否有人有任何建議,將不勝感激。非常感謝與此問題相關的任何幫助和時間。
答案1
嘗試:
$ awk 'f{a=a"\n"$0} /Condition 1/{a=$0; f=1} f && /Condition 2/{print a; f=0}' output.out
Condition 1: B
data2
Condition 2: C
Condition 1: E
data5
Condition 2: F
怎麼運作的
f{a=a"\n"$0}
如果變數
f
為真(非零),則將目前行附加到變數的末尾a
。/Condition 1/{a=$0; f=1}
如果目前行包含
Condition 1
,則設定s
為目前行並將變數設為f
1。f && /Condition 2/{print a; f=0}
如果
f
為 true 並且當前行包含Condition 2
,則列印變數a
並設定f
回零。
答案2
當您希望在文字處理中進行反向尋址時,請使用ex
它是POSIX 指定vi
,它是(以及vi
它的直接前身)的可編寫腳本的形式——非常靈活。
printf '%s\n' 'g/Condition 2/?Condition 1?,.p' | ex output.out
這意味著:
對於與模式「條件 2」相符的每一行(g
全域),請向後搜尋「條件 1」的前一個實例,並p
列印從該行到目前行 ( .
) 的所有行(即帶有「條件2」的行)它)。
提供的輸入的輸出與您所描述的完全相同。
答案3
sed 'H;/PATTERN_1/h;/PATTERN_2/!d;x' infile
儘管這假設任何匹配的行PATTERN_2
前面至少有一個匹配的行PATTERN_1
。對於更一般的情況,請添加另一個條件來PATTERN_1
在列印之前測試模式空間中是否存在:
sed 'H;/PATTERN_1/h;/PATTERN_2/!d;x;/PATTERN_1/!d' infile
答案4
這是 Perl 的一個邪惡之處:
perl -0777 -ne '
my $c1 = qr/Condition 1/;
my $c2 = qr/Condition 2/;
print for map {s/$c2.*?\n\K.*//s; $_}
grep {/$c2/}
split /(?=$c1)/ms;
' output.out
它:
- 讀取整個檔案(使用
-0777
和-n
選項), - 在出現條件 1 的位置將其拆分 (
split
), - 過濾掉條件 2 未出現的段落 (
grep
), - 然後從每個感興趣的段落中刪除條件 2 行 (
map
) 之後的所有行。