2015-08-22 72 views
1

我想爲每個可能的3位數字排除/刪除最後一行模式{n} {n} {n} .log。每行以樣本模式「123.log」結尾。刪除最後發生的模式行

樣品輸入文件:

aaaa116.log 
a112.log 
aaa112.log 
a113.log 
aaaaa112.log 
aaa113.log 
aa112.log 
aaa116.log 
a113.log 
aaaaa116.log 
aaa113.log 
aa114.log 

輸出文件:

aaaa116.log 
a112.log 
aaa112.log 
a113.log 
aaaaa112.log 
aaa113.log 
aaa116.log 
a113.log 

這怎麼可能通過的bash腳本來執行?

回答

1

刪除awk中的最後一條匹配行並不保留順序非常簡單。

awk -F'[^0-9]+' '/[0-9]+\.log$/ { 
    t = $(NF - 1); 
    if (t in a) 
     print a[t]; 
    a[t] = $0; 
}' 

保持輸出的順序更復雜,並且需要更多的內存。

awk -F'[^0-9]+' '/[0-9]+\.log$/ { 
    t = $(NF - 1); 
    a[++i] = $0; 
    b[$0] = t; 
    c[t] = i; 
} 
END { 
    for (n = 1; n <= i; n++) 
     if (n != c[b[a[n]]]) 
      print a[n]; 
}' 

穿過在第1例的next語句可以被添加到動作非匹配線,和1圖案可以附加。對於第二個例子,可以將數組a分配給它自己的操作。

+0

那麼,這正確地爲我的示例輸入工作,但出人意料地不適合我的真實數據。我可能錯過了什麼概括這個腳本? '/opt/appname/log/CL_20150820_000218_000_10015.log /opt/appname/log/CL_20150820_001519_000_10013.log /opt/appname/log/CL_20150820_094948_000_10016.log /opt/appname/log/CL_20150820_120048_000_10013.log /選擇/應用程序的名字/日誌/ CL_20150821_000017_000_10013.log /mnt/app/log/CL_20150821_140317_000_10016.log /mnt/log/CL_20150821_140319_000_10012.log /mnt/log/CL_20150821_171141_000_10012.log 到/ mnt /日誌/ CL_20150822_000010_000_10012.log' –

+1

它正在使用所有數字來檢查唯一性,使用'awk'變得更容易的格式。記錄$/{a [++ i] = $ 0; b [$ 0] = $ NF + 0; c [$ NF + 0] = i}'awk -F_'$ NF〜/ [0-9] END {for(n = 1; n <= i; n ++)if(n!= c [b [a [n]]])print a [n]}' – kdhp

+0

固定,工作正常。謝謝。 :) –

1

awk可能是最簡單的工具。例如,這一個班輪

tac file | awk 'match($0, /[0-9]{3}.log/,a) && a[0] in b; {b[a[0]]}' | tac 

產生樣本輸入請求的輸出。這並不要求將整個文件存儲在內存中。

更改正則表達式以適應您的特定需求。

+0

在「或」處或附近出現語法錯誤。 –

+1

@Yiğit我用GNU awk('gawk')測試過它,它似乎工作。也許我正在使用一些GNU特定的語法。嘗試在你的系統上安裝GNU awk,看看它是否有效。 – user000001

+1

匹配()的第三個參數是特定於gawk的。如果您使用的是gawk,但不確定您是否使用gawk擴展名,請嘗試將腳本作爲'gawk --posix'運行。 –

1
$ awk '{k=substr($0,length()-7)} NR==FNR{n[k]=NR;next} FNR!=n[k]' file file 
aaaa116.log 
a112.log 
aaa112.log 
a113.log 
aaaaa112.log 
aaa113.log 
aaa116.log 
a113.log