2009-11-03 67 views
62

如何根據某種表達方式使sed篩選匹配行,但忽略不匹配的行,而不是讓它們打印?已經sed忽略不匹配的行

作爲一個實例,我想在一組文件上運行scalac(Scala編譯器),並從其-verbose輸出中讀取輸出的.class文件。 scalac -verbose會輸出一堆消息,但我們只對[wrote some-class-name.class]這種形式感興趣。 什麼我目前做的是這個(|&是bash的4.0對管標準錯誤的方式到下一個程序):

$ scalac -verbose some-file.scala ... |& sed 's/^\[wrote \(.*\.class\)\]$/\1/' 

這將提取我們感興趣的消息的文件的名稱,但會也讓所有其他消息通過不變!當然,我們可以這樣做,而不是這樣的:

$ scalac -verbose some-file.scala ... |& grep '^\[wrote .*\.class\]$' | 
    sed 's/^\[wrote \(.*\.class\)\]$/\1/' 

其作品,但看起來非常像周圍的真實問題,這就是如何指導sed忽略從輸入不匹配的行會。那麼我們該怎麼做?

回答

65

用普通的另一種方式的sed:

sed -e 's/.../.../;t;d' 

s///是substituion,t沒有任何標籤有條件跳過所有下面的命令,d刪除線。

不需要perl或grep。

(尼古拉斯·萊利的建議後編輯)

+3

在OS X 10.8.2上,當我得到'undefined label'x; d;:x''時,我必須用換行符而不是分號來分隔'tx'和'd'。 – davidchambers

+4

更好:'sed -e's /.../.../'-e'tx'-e'd'-e':x''(在[類似問題](http ://stackoverflow.com/a/1252191/312785))。 – davidchambers

+1

如果沒有提供標籤,'t'將轉移到腳本的末尾,因此更簡單:'sed -e's /.../.../'-e't'-e'd''。 –

3

使用Perl:

... |& perl -ne 'print "$1\n" if /^\[wrote (.*\.class)\]$/' 
164

如果你不希望打印不匹配的行,你可以使用不告訴桑達

  • -n選項的組合打印
  • p標誌告訴sed打印什麼匹配

這給出:

sed -n 's/.../.../p' 
+7

這應該是公認的答案 –

+1

一個缺點這種方法,如果您有匹配多個表達式,其結果也將被打印多次。例如:'echo foo | sed -n -e's/foo/bar/p'-e's/bar/oof/p''將在單獨的行上輸出'bar'和'oof'。儘管goto標籤變種不能處理多種模式,但是如果第一種模式不匹配,它將刪除該行。 – Rapsey