2013-03-04 25 views
3

我需要用多個文件中的另一個正則表達式替換所有正則表達式的實例,這些文件位於根目錄下的多個目錄中。在多個文件中替換正則表達式

例如: 文件結構:

. 
|---src 
| |---Module 
| | |---someclass.cpp 
| |---main.cpp 
| 
|---include 
    |---Module 
     |---someclass.hpp 

基本上是但更多的文件和文件夾。

我需要搜索正則表達式\(std::vector<.*>\(std::vector<.*> const& 最棘手的部分似乎是確保之間<>保持不變的內容替換它的所有實例。

例如,它將匹配(std::vector<int>並將其替換爲(std::vector<int> const&。 一個更復雜的例子是:
比賽:(std::vector<std::map<std::string, int>>
替換爲:(std::vector<std::map<std::string, int>> const&

+0

[你有什麼試過?](http://mattgemmell.com/2008/12/08/what-have-you-tried/) – 2013-03-04 09:51:13

回答

4

如果最終「>」在你的例子是最後的「>」在每一行,然後這應該工作:

find root -name '*.cpp' -print0 | 
xargs -0 sed -i 's/\((std::vector<.*>\)\([^>]*$\)/\1 const\&\2/' 

儘量sed的一個單一的文件,並沒有-i第一,如:

$ cat file 
(std::vector<int> 
(std::vector<int> foo 
(std::vector<std::map<std::string, int>> 
(std::vector<std::map<std::string, int>> bar 

$ sed 's/\((std::vector<.*>\)\([^>]*$\)/\1 const\&\2/' file 
(std::vector<int> const& 
(std::vector<int> const& foo 
(std::vector<std::map<std::string, int>> const& 
(std::vector<std::map<std::string, int>> const& bar 

如果在你的例子中的最後一個之後可以有「>」,那麼解決方案非平凡,發佈一些有代表性的樣本輸入和期望的輸出。

哦,究竟發生了什麼,這裏是不平凡的腳本:

$ cat file 
(std::vector<int> 
(std::vector<int> foo 
(std::vector<int> with extra > in text 
(std::vector<std::map<std::string, int>> 
(std::vector<std::map<std::string, int>> bar 
(std::vector<std::map<std::string, int>> and here is > again 

$ awk -v FS= -v str="(std::vector<" ' 
BEGIN{ lgth=length(str) } 
start=index($0,str) { 
    cnt = 1 
    for(i=(start+lgth);(i<=NF) && (cnt!=0);i++) { 
     if ($i == "<") cnt++ 
     if ($i == ">") cnt-- 
    } 
    $0 = substr($0,1,i-1) " const&" substr($0,i) 
}1' file 
(std::vector<int> const& 
(std::vector<int> const& foo 
(std::vector<int> const& with extra > in text 
(std::vector<std::map<std::string, int>> const& 
(std::vector<std::map<std::string, int>> const& bar 
(std::vector<std::map<std::string, int>> const& and here is > again 

做一個while循環中:

find root -name '*.cpp' -print | 
while IFS= read -r file; do 
    awk -v FS= -v str="(std::vector<" ' 
    BEGIN{ lgth=length(str) } 
    start=index($0,str) { 
     cnt = 1 
     for(i=(start+lgth);(i<=NF) && (cnt!=0);i++) { 
      if ($i == "<") cnt++ 
      if ($i == ">") cnt-- 
     } 
     $0 = substr($0,1,i-1) " const&" substr($0,i) 
    }1' "$file" > tmp && 
    mv tmp "$file" 
done 

如果你的文件名中包含換行符這不會工作,但無論如何,你應該修正這些問題。

+0

工作完美無瑕,非常感謝你。 – xNidhogg 2013-03-04 12:49:43

+0

在Mac上,需要使用附加-E來啓用擴展(現代)正則表達式:sed -E -i ... – 2015-06-25 11:06:00

+0

@ Mr.Napik True,但以上sed腳本都不使用ERE,因此不需要。 – 2015-06-25 12:49:00

0

您將需要使用不同的正則表達式分別處理您的簡單和複雜的情況下。正則表達式不能計算嵌套項目並對此進行計算。

替換的嵌套:\(std\:\:vector\<([^\<\>]*)\>

然後用單築巢代替:\(std\:\:vector\<([^\<\>]*\<[^\<\>]*\>[^\<\>]*)\>