2009-06-12 65 views
1

我想按照一些規則對項目執行批量替換操作。對於例如我在這樣的代碼中記錄:如何在代碼中替換字符串

對於每個代碼片段,我都要執行替換操作,它將用以下示例中的輸出代碼片段替換輸入代碼片段:

輸入1:

//+ 
a++; 
//+(+SomeException$SomeMessage) 

輸出1:

try 
{ 
    a++; 
} 
catch (AnException) 
{ 
    throw; 
} 
catch (Exception ex) 
{ 
    throw new SomeException("SomeMessage", "15", ex); 
} 

輸入2:

//+ 
a++; 
//-(+InvalidOperationException$SomeMessage) 

輸出2:

try 
{ 
    a++; 
} 
catch (InvalidOperationException ex) 
{ 
    throw new AnException("SomeMessage", "16", ex); 
} 

輸入3:

//+ 
a++; 
//-(SomeMessage) 

輸出3:

try 
{ 
    a++; 
} 
catch (Exception ex) 
{ 
    throw new AnException("SomeMessage", "17", ex); 
} 

幻數(15,16,17)將增加每個代碼塊這樣評論。我知道這不是最佳做法,但我沒有做出決定,我期望能夠處理這樣的例外情況,所以我認爲我可以通過記筆記和批量更換來緩解痛苦。做這個的最好方式是什麼?我應該編寫自己的代碼來執行替換嗎?還是有一些正則表達式替換工具或類似的東西可以自動爲我做這件事?

更新:這是一次性工作,我的幻數必須是全球唯一的。所以如果在文件中的最後一場比賽中是25,那麼下一個文件中的第一場比賽必須是26。

回答

0

這看起來像一個簡單的語言,您將編譯成看起來像Java的另一種語言。編譯器是適合這樣工作的正確工具,尤其是因爲您需要保持當前幻數的狀態。似乎任何決策者都希望爲語言添加新的功能,在這種情況下,用正則表達式粘在一起的解決方案可能無法正常工作。

如果我對你真正想要的東西是正確的,那麼你的問題就會歸結爲「我如何寫域特定語言?」這個問題。我不確定最好的方法是什麼,但如果你知道Perl,你可以用Parse::RecDescent來組合一個解決方案。

我認爲這可能是通過腳本和正則表達式來實現的,但這是編譯器發明的問題類型。如果你最終做出一件怪事,上帝會幫助那些在你身後維護它的人! :)

+0

不幸的是,我不知道Perl和我不是想寫一個DSL。我只想替換我的代碼中的一些字符串,並增加每場比賽的魔術數字。 – 2009-06-12 22:25:26

+0

我認爲你正在嘗試實現你的源代碼的評論中存在的DSL。這聽起來像是爲你寫的。 :) 像這樣的實現操作不僅僅是一個簡單的搜索和替換問題,您需要解析輸入並根據輸入被解析的方式發出符號。這是編譯器的工作,你可能需要編寫或使用它。 – 2009-06-12 22:49:00

0

您可以編寫一個CodeSmith模板來讀取該輸入並輸出該輸出。但是,我不確定你是否可以在線進行。也就是說,你需要一個只有輸入的文件,然後你的模板可以給你輸出文件。我不確定那是否可以接受的壽命。

+0

我看了代碼史密斯教程,我想我可以使用實際的.cs文件作爲模板。我希望它能將一個狀態從一個模板文件轉移到另一個狀態,因爲這個幻數必須是全局唯一的。 – 2009-06-12 22:30:19

0

有很多方法可以做到這一點,即使你可能不應該(你似乎意識到,這隻會導致無意義的例外)。不過,這是一個sed/sh組合來完成第一個。它不處理自動編號或其他變體。我將把它作爲OP的練習。

P1='\/\/+'; P2='\(.*\)'; P3='\/\/+(+\([^$]*\)$\(.*\))'; 
echo 'foo()\n//+\na++\n//+(+SomeException$Message)'|sed ' /'$P1'/ { N; /'$P2'/ { N; /'$P3'/ { s/'$P1'\n'$P2'\n'$P3'/try\n{\n\t\1\n}\ncatch (AnException)\n{\n\tthrow;\n}\ncatch (Exception ex)\n{\n\tthrow new \2("\3", "0", ex);\n}/ } } } ' 

echo只是一個測試字符串。

+0

非常感謝大量的正則表達式寫入時間,但是一旦我找出正確的工具或方法,我想我可以自己組成正則表達式。這裏最大的問題是自動編號。 – 2009-06-12 22:53:40

1

這樣做的最好方法是什麼?我應該編寫自己的代碼來執行替換嗎?還是有一些正則表達式替換工具或類似的東西可以自動爲我做這件事?

我會用C++或C#編寫一個小程序來做到這一點。據推測,其他工具和腳本語言可以做到這一點;但考慮到在C++或C#中這是一項微不足道的工作,並且我已經知道如何在這些語言中完成它,爲什麼不呢?

我不知道你是什麼意思的「最好」的方式,但對我來說,至少這將是最簡單的方法之一。

0

作爲一名Emacs用戶,對於一次性工作,我會通過定義鍵盤宏 來完成此操作,然後使用set/increment/insert-register作爲自動編號魔術。 應該不需要編寫自己的elisp函數。

雖然如果您需要在不止一兩個文件上執行此操作,您可能會更好地編寫腳本來完成這項工作。

0

如果你沒有碰巧使用像Emacs這樣的IDE(許多人回答)並且支持強大的正則表達式,我會寫一個小腳本。注意,文本操作通常更多是腳本操作,例如, Perl,Ruby,因爲語言本身支持正則表達式。另一方面,如果您非常熟悉Java Pattern,那麼即使您需要更多開銷,使用Java編寫它也是最快的解決方案。一次性操作。

所以豆蔻Ruby腳本可能看起來像(注意,我沒有測試):

$cnt = 1 
IO.readlines(filename).collect { |line| 
    if line =~ /^\s*\/\/\+\s*$/ 
    $cnt += 1 
    ["try\n", "{\n" ] 
    elsif line =~ /^\s*\/\/\+\(\+(.+)\$(.+)\)\s*/ 
    ["}\n", "catch (#{$1} ex)\n", "{\n", 
     "throw new AnException(\"#{$2}\", \"#{$cnt}\", ex);\n", "}\n"] 
    # propably more else for all cases 
    else 
    line 
    end 
}.flatten 
# save the file again