2012-06-03 50 views
2

我已經改變了我的董事結構,我要做到以下幾點:遞歸查找和替換基於正則表達式

  • 執行遞歸grep來找到比賽的所有實例
  • 切換到更新的位置串

一個例子(出數以百計的)是:

from common.utils import debug --> from etc.common.utils import debug 

要獲得LL的什麼我正在尋找我做的實例:

$ grep -r 'common.' ./ 

不過,我也需要確保common是前面有一個空格。我將如何做這個查找和替換?

+0

egrep是Solaris命令afaikr。 –

+3

@RobKielty'egrep'是至少所有的GNU系統,簡稱'grep的-E'(擴展的正則表達式,你其實並不需要在這裏) – Kevin

+1

此外,OP,你想'\ .',而不僅僅是一個' .';否則它被解釋爲除了換行符之外的任何內容。 – Kevin

回答

4

很難準確地告訴你想要什麼,因爲重構示例更改了導入以及包,但以下內容將更改爲common. -> etc.common.目錄中的所有文件:

sed -i 's/\bcommon\./etc.&/' $(egrep -lr '\bcommon\.' .) 

這假定你有gnu sed可用,大多數linux系統都可以。此外,只是爲了讓你知道,如果sed要處理的文件太多,這將會失敗。在這種情況下,你可以這樣做:

egrep -lr '\bcommon\.' . | xargs sed -i 's/\bcommon\./etc.&/' 

注意,這可能是一個好主意,因爲sed -i'.OLD' 's/\bcommon\./etc.&/'運行sed命令,讓你得到的原始文件的備份。

+0

感謝您指出,這是一個錯字。 – David542

1

這大致上是你如何使用find來做到的。這就要求測試

find . -name \*.java -exec sed "s/FIND_STR/REPLACE_STR/g" {} 

這意味着作爲「從當前目錄開始發現,在.java結尾的所有文件和文件執行SED(其中{}是一個佔位符爲當前找到的文件)」 S/FIND_STR/REPLACE_STR/g「在當前文件的每行中用REPLACE_STR替換FIND_STR

+0

爲什麼你有'1,$'? sed *已經*在'1,$'上運行。 –

+0

vi習慣的力量。我刪除它。 –

1

如果您grep實現支持Perl語法(-P標誌上,例如Linux的它通常用),你可以從附加功能中受益,如文字界限:

$ grep -Pr '\bcommon\.' 

順便說一句:

grep -r往往比之前管道式的find命令慢得多,如Rob的例子。此外,當你確定發現的文件的名稱不包含任何空格,使用xargs-exec快得多:

$ find . -type f -name '*.java' | xargs grep -P '\bcommon\.' 

或者,適用於Tim的例子:

$ find . -type f -name '*.java' | xargs sed -i.bak 's/\<common\./etc.common./' 

注意在後面的例子中,替換是在爲每個更改的文件創建一個* .bak備份後完成的。這樣,您就可以查看該命令的結果,然後刪除備份:

$ find . -type f -name '*.bak' | xargs rm 

如果你已經做了一個oopsie,下面的命令將恢復到以前的版本:

$ find . -type f -name '*.bak' | while read LINE; do mv -f $LINE `basename $LINE`; done 

當然,如果你不知道文件名和路徑中是否有空白,則應通過find-exec參數應用命令。

乾杯!

+0

對於簡單的單詞邊界,您不需要'-P',但是它們在'egrep'中是左邊的'\ <'和右邊的'\>'。 – tripleee

+0

謝謝。這就是我在閱讀蒂姆的帖子後想到的。我立即在我的'vi'中嘗試過。當然,它有效。然後我問自己這些年來我做了些什麼。現在我不知道我是否應該對這個新的功能感到高興,或者對所有浪費的時間哭泣...... – mjhennig

+0

@tripleee egrep也支持單詞邊界的'\ b'。 '\ <' and '\>'只是'\ b'的邊緣特定版本。 –