2012-02-08 24 views
12

我是一名Perl程序員,他嘗試通過完成我之前完成的一些工作來學習Python,並將其轉換爲Python。這是不是一行一行的翻譯。我想學習Python技術來完成這種類型的任務。在Python中解析行:使用RE還是不行?

我正在解析Windows INI文件。部分名的格式爲:

[<type> <description>] 

<type>是一個字的字段,並且不區分大小寫。 <description>可能是多個單詞。

段落後,有一堆參數和值。這些都是形式:

<parameter> = <value> 

參數沒有空格,只能包含下劃線,字母和數字(不區分大小寫)。因此,第一個=是參數和值之間的分隔符。在等號周圍可能會有空格分隔參數和值。行首或行尾可能會有額外的空白。

在Perl中,我用正則表達式解析:

while (my $line = <CONTROL_FILE>) { 
    chomp($line); 
    next if ($line =~ /^\s*[#;']/);  #Comments start with "#", ";", or "'" 
    next if ($line =~ /^\s*$/);   #Ignore blank lines 

    if ($line =~ /^\s*\[\s*(\w+)\s+(.*)/) { #Section 
     say "This is a '$1' section called '$2'"; 
    } 
    elsif ($line =~ /^\s*(\w+)\s*=\s*(.*)/) { #Parameter 
     say "Parameter is '$1' with a value of '$2'"; 
    } 
    else {  #Not Comment, Section, or Parameter 
     say "Invalid line"; 
    } 

} 

的問題是,我已經被Perl損壞,所以我覺得做一些最簡單的方法是使用正則表達式。下面的代碼我到目前爲止...

for line in file_handle: 
    line = line.strip 

    # Comment lines and blank lines 
    if line.find("#") == 1 \ 
      or line.find(";") == 1 \ 
      or line.whitespace: 
     continue 

    # Found a Section Heading 
    if line.find("[") == 1: 
     print "I want to use a regular expression here" 
     print "to split the section up into two pieces" 
    elif line.find("=") != -1: 
     print "I want to use a regular expression here" 
     print "to split the parameter into key and value" 
    else 
     print "Invalid Line" 

有幾件事情,在這裏激怒我:

  • 有兩個地方,一個正則表達式似乎只是被呼叫使用。什麼是Python分裂的方式?
  • 我確保去掉字符串兩邊的空白區域,然後重寫字符串。這樣,我不必多次進行剝離。但是,我正在重寫字符串,我知道這是Python中非常低效的操作。什麼是Python的方式來處理這個問題?
  • 最後,我的算法看起來非常像我的Perl算法,這似乎說我讓我的Perl思維成爲現實。我的代碼應該如何在Python中構造?

我一直在閱讀各種在線教程,他們幫助我理解語法,但在處理語言本身方面卻沒有太多 - 尤其是那些傾向於在另一種語言中思考的人語言。

我的問題:

  • 我應該使用正則表達式?或者,還有另一種更好的方法來處理這個問題嗎?
  • 我的編碼邏輯是否正確?我應該如何考慮解析這個文件?
+3

請務必查看['ConfigParser'](http://docs.python.org/library/configparser.html)模塊。 – 2012-02-08 21:33:30

+0

在Perl中你不會'腐敗',你'保佑' – joaquin 2012-02-08 21:48:10

+0

@SvenMarnach - 謝謝你的建議,但我已經看到了。問題在於ConfigParser將輸出放到字典中,我不能保證字典中的部分的順序在這個特定的應用程序中非常重要。我用[Config :: Ini](http://search.cpan.org/~rjbs/Config-INI-0.019/lib/Config/INI.pm)模塊對Perl有同樣的問題。此外,這讓我有機會真正瞭解Python的來龍去脈。 – 2012-02-08 21:55:42

回答

4

雖然我不認爲這是你的意圖,但文件格式看起來與Python的內置ConfigParser模塊非常相似。有時最爲「Pythonic」的方式已經爲您提供。 (:

更直接回答你的問題:正則表達式可以做到這一點的好辦法,否則,你可以嘗試更基本的(和不太可靠)

(parameter, value) = line.split('=') 

這將拋出一個錯誤如果線路不包含或超過一個「=」字符您可能希望與'=' in line首先測試它

。另外:

line.find("[") == 1 

可能是更好通過

line.startswith("[") 

。希望helpls一點(改爲:

+0

謝謝,我真的看到了這個模塊,但不幸的是,它將結果存儲在字典中,並且可能會丟失這些部分的讀取順序。對我而言,這些部分的順序非常重要。我使用[Config :: Ini](http://search.cpan.org/~rjbs/Config-INI-0.019/lib/Config/INI.pm)模塊在Perl中遇到同樣的問題。此外,這個想法是學習語言。感謝指向'startswith'方法的指針。 – 2012-02-08 21:58:54

+0

@大衛不客氣。我認爲內置的方式不會是完全相同的,不知何故... :) – tjvr 2012-02-08 22:12:32

+0

爲了避免超過1'='標誌,使用'line.split('=',1)'也解決了問題no'='符號,使用'parameter,value =(line.split('=',1)+ [''])[:2]'。不要把()圍繞LHS元組,它們是不必要的混亂。另外一定要使用'line.strip()'調用'line.strip' - 你的代碼將用綁定的方法條代替行,我敢肯定這是不希望的。 – PaulMcG 2012-02-08 23:55:46

5

Python包括一個ini parsing library。如果您想構建一個庫來解析ini文件,那麼您正在查看實際的解析器。正則表達式不會削減它,使用PLY或掛鉤在flex/bison C語法分析器中。Additional python parsing resources are available as well

詞庫處理所有的文本消費和樹的構造,因爲它是一個容易出現程序員錯誤的機械任務。 I.E.此部分:

while (my $line = <CONTROL_FILE>) { 
    chomp($line); 
    next if ($line =~ /^\s*[#;']/);  #Comments start with "#", ";", or "'" 
    next if ($line =~ /^\s*$/);   #Ignore blank lines 

    if ($line =~ /^\s*\[\s*(\w+)\s+(.*)/) { #Section 
     say "This is a '$1' section called '$2'"; 
    } 
    elsif ($line =~ /^\s*(\w+)\s*=\s*(.*)/) { #Parameter 
     say "Parameter is '$1' with a value of '$2'"; 
    } 
    else {  #Not Comment, Section, or Parameter 
     say "Invalid line"; 
    } 

} 

由詞法分析器創建,您只需要定義正確的正則表達式。解析器從詞法分析器中提取令牌,並確定它們是否符合允許的令牌模式。即:

[<type> <description>] 
<parameter> = <value> 

定義這些令牌,然後如何允許擬合。其他一切只是把自己放在一起。對於那些認爲你可以在快速循環和一些正則表達式中做得更好的人,我建議你閱讀Lex & Yacc, 2nd Ed.

對於我用PLY編寫的示例解析器,go here。它分析一個「jetLetter」文件,它只是一個方言groff/troff

+0

+1顯示瞭如何執行大量事情的'Python'方式經常知道庫中強大的構建。 – 2012-02-08 21:41:36

+0

只是想拋出一個鏈接到[lepl](http://www.acooke.org/lepl/),這是我最近在這個網站上了解到的一個不錯的,輕量級的解析庫。 – 2012-02-08 21:44:42

0

是,通過各種手段使用正則表達式在這種情況下。您嘗試解析的.INI文件行的語法在數學上符合喬姆斯基3型(常規)語法的特徵,這正是正則表達式旨在解析的東西。

您所需要的正則表達式(從我的頭頂,未經測試)類似:

r"^\[\s*(\w)\s+(.*)\]$" 

r"^(\w)\s*\=\s*(.*)$" 

使用re.search,並在返回的Match objects,可以提取這些組對應於表達式中的括號分組。

相關問題