2010-01-26 71 views
6

我們在幾個類中有一個ArrayList項目,每次我想要插入一個新項目時都會給我帶來麻煩。我以我的方式設計課程是一個錯誤,但現在改變設計會比它的價值更令人頭痛(官僚的瀑布模型)。我應該預料到客戶提供給我們的文檔的格式變化被詛咒。使用正則表達式重新格式化代碼

我想寫一個簡單的腳本在python中進入一個類,將項目添加到列表中,然後增加下列項目的所有檢索。這聽起來很說明:

Foo extends Bar{ 
    public Foo(){ 
     m_Tags.add("Jane"); 
     m_Tags.add("Bob"); 
     m_Tags.add("Jim"); 
    } 

    public String GetJane() { return m_ParsedValue.get(m_Tags.get(1)); } 
    public String GetBob() { return m_ParsedValue.get(m_Tags.get(2)); } 
    public String GetJim() { return m_ParsedValue.get(m_Tags.get(3)); } 
} 

你看,如果我要「簡」之間添加值「鮑勃」我接下來要增加在Get *函數整數。我只想在Python中編寫一個簡單的腳本,爲我完成這項工作。有人我非常尊重建議的正則表達式。

編輯:

是的,LinkedHashMap。如此簡單,如此簡單,現在不在設計規格中。我討厭瀑布。用激情憎恨它。這整個過程是一個「小」和「容易」的部分,「不應該花太多時間來設計」。我犯了錯誤。它現在陷入困境。

+4

讓我得到這個直:你擁有一個充滿魔力巨大,難以管理的Java代碼質量數字和硬編碼字符串,你想在中間插入一個,並使用python增加下面的數字? – Jorenko

+0

爲什麼你不使用HashMap?只需使用字符串作爲鍵,並返回你想要的數字...似乎更自然的方式來做到這一點。 – Khelben

+0

@Jorenko:是的,沒有。這些字符串取自專有格式的客戶文件,並傳遞給我們的應用程序。代碼不是很大,並且不違反DRY。但是,你是對的。有大量的魔術數字,是的,我想在中間插入一個。 – wheaties

回答

4

您希望您的正則表達式與編譯器針對標記之間的空白一樣靈活。這樣做和模仿空白使用會使模式非常混亂。下面的代碼(對不起:Perl,不是Python)就地編輯你的源文件。

#! /usr/bin/perl -i.bak  
use warnings; 
use strict; 
my $template = 
    '^(public 
     String 
     Get)(\w+)(\(\) { return 
     m_ParsedValue . get \(m_Tags . get \()(\d+)(\) \) ; })$'; 
$template =~ s/ +/\\s*/g; 
$template =~ s/(\r?\n)+/\\s+/g; 
my $getter = qr/$template/x; 

die "Usage: $0 after new-name source ..\n" unless @ARGV >= 3; 
my $after = shift; 
my $add = shift; 
my $index; 
while (<>) { 
    unless (/$getter/) { 
    print; 
    next; 
    } 
    my($abc,$name,$lmno,$i,$xyz) = ($1,$2,$3,$4,$5); 
    if (defined $index) { 
    print join "" => $abc, $name, $lmno, ++$index, $xyz; 
    } 
    else { 
    if ($name eq $after) { 
     $index = $i; 
     print; print join "" => $abc, $add, $lmno, ++$index, $xyz; 
    } 
    else { print; } 
    } 
} 

例如,

$ ./add-after Jane Foo code.java 
$ cat code.java 
Foo extends Bar{ 
    public Foo(){ 
     m_Tags.add("Jane"); 
     m_Tags.add("Bob"); 
     m_Tags.add("Jim"); 
    } 

    public String GetJane() { return m_ParsedValue.get(m_Tags.get(1)); } 
    public String GetFoo() { return m_ParsedValue.get(m_Tags.get(2)); } 
    public String GetBob() { return m_ParsedValue.get(m_Tags.get(3)); } 
    public String GetJim() { return m_ParsedValue.get(m_Tags.get(4)); } 
}
+0

非常感謝。我可以將它展示給知道perl和python的人。他們將能夠引導我回來。 – wheaties

+0

不客氣。我很高興它有幫助。 –

4

不要這樣做與正則表達式。創建將名稱映射到數字的符號常量(使用例如枚舉)。

+0

從技術上講,如果我必須從頭開始重新設計,我會爲每個組件創建一個命名變量,將它們分配給列表,然後將該列表傳遞給解析函數。那麼我不需要處理所有這些神奇的數字。 – wheaties

+0

你不需要重新設計。現在只需添加常量。然後有腳本,如果你必須使用它,增加常量。 – vy32

0

我現在正在做這件事(當然,非常相似),但使用Excel和VBA宏。所有的商業價值都在電子表格中進行組織和排序。我只需點擊一個按鈕爲所選單元格生成適當的代碼,然後複製粘貼到IDE。更好的是,我爲每一行都有幾個「代碼列」。其中一些生成查詢,一些XSL轉換和一些過程。對於一行商業數據,我可以很容易地獲得所有三種類型的生成代碼。

我發現這(重新生成)比重新格式化我現有的代碼要容易得多。

+0

這聽起來像是一個系統的噩夢。 –

+0

@matt b:起初我也是這麼想的。分析師維護電子表格中的業務數據(他們實際上組織得非常好),所以我可以輕鬆地獲取它們的副本,然後應用我的宏來獲取很多很少需要手動調整的樣板代碼。它的開發速度非常快,並且與業務需求完全匹配 - 這也有助於發現需求中的錯誤。 – FrustratedWithFormsDesigner

4

評論相距約壞的做法 - 在這裏是在你所要求的語言要求的代碼。 如果你用這種方式保存系統,最好的辦法可能是讓這些java文件在構建過程中自動生成 - 你只需要在目錄中的.txt文件中保存一個名稱列表。這個腳本適合做到這一點。

(它不會修改你的文件,它的基礎上,你張貼在這裏的模板genrate新)

import re, sys 

template = """Foo extends Bar{ 
    public Foo(){ 
%s 
    } 

%s 
} 
""" 

tag_templ = """  m_Tags.add("%s");""" 
getter_templ = """ public String GetJane() { return m_ParsedValue.get(m_Tags.get(%d)); }""" 

def parse_names(filename): 
    data = open(filename).read() 
    names = re.findall(r'm_Tags\.add\("(.*?)"', data) 
    return names 

def create_file(filename, names): 
    tag_lines = [tag_templ % name for name in names] 
    getter_lines = [getter_templ % (i + 1) for i in range(len(names))] 
    code = template % ("\n".join(tag_lines), "\n".join(getter_lines)) 
    file = open(filename,"wt") 
    file.write(code) 
    file.close() 

def insert_name(after, new_name, names): 
    names.insert(names.index(after) + 1, new_name) 

if __name__ == "__main__": 
    if len(sys.argv) < 4: 
     sys.stderr.write("Usage: changer.py <filename> <name-before-insertion> <new-name>") 
     sys.exit(1) 
    filename, name_before, new_name = sys.argv[1:] 
    names = parse_names(filename) 
    insert_name(name_before, new_name, names) 
    create_file(filename, names) 
+0

非常感謝,感謝不要評論我的錯誤。這真是一個好主意。我一直在試圖採取更實際的方法(一個月前完成了實用程序員)。 – wheaties

+0

模板絕對是正確的選擇。但爲什麼不更進一步,並使用真正的模板庫,如模板工具包for Python? http://tt2.org/python/index.html – daotoad

+0

在這樣一個簡單的例子中,沒有必要這樣做嗎? Python motos之一是「簡單勝於複雜」 - 即使對於真實代碼,標準庫本身也有足夠好的模板格式化方法來證明這種簡單情況下的外部依賴性。 – jsbueno

相關問題