2012-01-31 45 views
1

如何使用perl搜索兩個順序換行符(\ n)?或者更具體地說,爲什麼即使它們存在,搜索也不成功?我有一個連續換行符的文件(使用十六進制編輯器來完成,它們不是返回值等),但是perl似乎並不接受這個正則表達式。如何使用perl搜索兩個連續換行符( n)?

的perl -pi -e 'S/\ n \ n /測試/ G' 將myfile.xml =沒有結果

實際上,我試圖插入一些代碼到XML文件,但換行符在中間,那麼最優雅的方式是什麼?我想出了一個可怕的perl單行文本,但是雙行文件似乎會導致失敗。

我想改變從一個gtkrc文件的一部分:

GtkWidget::link-color = @link_color 
GtkWidget::visited-link-color = @text_color 

#################### 
# Color Definitions 
#################### 

到:

GtkWidget::link-color = @link_color 
GtkWidget::visited-link-color = @text_color 

GtkWindow::resize-grip-height = 0 
GtkWindow::resize-grip-width = 0 

#################### 
# Color Definitions 
#################### 

使用的原代碼的一部分作爲我的搜索詞(也有各自之前的標籤在原始腳本線上,順便說一句),我的查找和替換條款是:

color\n\n\t\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\n\t\# Color 

color\n\n\tGtkWindow::resize-grip-height = 0\n\tGtkWindow::resize-grip-width = 0\n\n\t\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\n\t\# Color 

我想出了這個大ugl Ÿperl的命令:

perl -pi -e 's/color\n\n\t\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\n\t\# Color/color\n\n\tGtkWindow::resize-grip-height = 0\n\tGtkWindow::resize-grip-width = 0\n\n\t\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\n\t\# Color/g' /usr/share/themes/Ambiance/gtk-2.0/gtkrc 

編輯:從扎伊德更正代碼:

perl -0777 -pi -e 's/color\n\n\t\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\n\t\# Color/color\n\n\tGtkWindow::resize-grip-height = 0\n\tGtkWindow::resize-grip-width = 0\n\n\t\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\n\t\# Color/g' /usr/share/themes/Ambiance/gtk-2.0/gtkrc 

如前所述,它似乎是\ n \ n表示出現問題的原因是什麼都可以更換。有什麼更好的方法來做到這一點?

我在Ubuntu 11.10上,命令將從shell腳本運行而不是perl腳本。

回答

2

當您打開一個文件進行讀取,該文件默認情況下逐行讀取。這是因爲輸入記錄分隔符$/設置爲換行符。

既然你打破了換行符上的每一個「行」,那麼理由是你永遠無法在一行中找到兩行換行符。

解決此問題的一種方法是,正如Zaid所說的,用-0標誌更改輸入記錄分隔符。只要新的輸入記錄分隔符不與你的正則表達式部分匹配,你就會沒事的。 (只要您不嘗試匹配.\n)。

讓我們讓你的正則表達式變得不那麼可怕。除非使用/x修飾符,否則不需要轉義#。您不需要連續使用幾個#字符,請使用量詞+, * or {x,y}

除了刪除一個字符串然後放回一個相同的字符串,還有一些選項可以避免兩次輸入相同的東西。

  • 您可以避免使用Lookaround Assertions刪除字符串。
  • 您可以使用\K作爲一個簡化的外觀,背後斷言(見上文)
  • 您可以捕捉字符串,將它們放回使用$1, $2 ...

在這種情況下,我的首選是使用一個後視斷言來查找「color \ n \ n」字符串,然後查找「Color」註釋。

perl -0777 -pwe 's/(?<=color\n\n)(?=[#\s]+Color)/INSERT\n\n/' /path/to/file 

哪裏INSERT當然是你要插入的文本,這是我的可讀性刪除。我還刪除了-i標誌,因此您可以先嚐試一下。

+0

我會給你一個鏡頭,謝謝。我認爲我需要轉義所有散列,因此從shell腳本運行時不會將其解釋爲註釋。正如你所指出的,我的解決方案是可怕的。捕捉字符串的使用更加優雅。我只有大約2天進入perl,並且有很多東西需要學習。 – Veazer 2012-01-31 16:42:25

+0

@ user30441這不是捕獲,它是查找斷言。在shell腳本中使用時,元字符會變得麻煩。將代碼放入腳本並調用它可能會更容易。例如。 'perl/home/script.pl'。 – TLP 2012-01-31 16:48:16

+0

感謝您的澄清。我試圖避免調用任何外部腳本,並且您的方法運行良好。 – Veazer 2012-01-31 17:01:02

3

您需要一次性加載整個文件以檢測\n\n。使用-0777覆蓋默認的行由行行爲:

$ perl -0777 -pi -e 's/\n\n/TEST/g' myfile.xml 
+0

完美。感謝您快速準確的答覆。我用正確的用法更新了我的問題。 – Veazer 2012-01-31 15:51:51

+0

+1雖然你在誇誇道說「你需要」。您只需使用任何其他輸入記錄分隔符讀取文件,而不是使用單個換行符。 – TLP 2012-01-31 16:13:06

+2

您的問題經常被問到,「我在多條線路上遇到問題,出了什麼問題?」 http://learn.perl.org/faq/perlfaq6.html#Im-having-trouble-matching-over-more-than-one-line.-Whats-wrong- – tadmc 2012-01-31 16:16:44

相關問題