在Python中解析行:是否使用RE?

Dav*_* W. 12 python for-loop

我是一名Perl程序员,他试图通过我之前完成的一些工作并将其转换为Python来学习Python.这不是逐行翻译.我想学习Python技术来完成这类任务.

我正在解析Windows INI文件.部分名称采用以下格式:

[<type> <description>]
Run Code Online (Sandbox Code Playgroud)

<type>是一个单词字段,不区分大小写.在<description>可能是多个单词.

在一节之后,有一堆参数和值.这些是以下形式:

 <parameter> = <value>
Run Code Online (Sandbox Code Playgroud)

参数没有空格,只能包含下划线,字母和数字(不区分大小写).因此,第一个=是参数和值之间的分隔符.在等号周围可能存在将参数和值分开的空白区域.在行的开头或结尾可能有额外的空白区域.

在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";
    }

}
Run Code Online (Sandbox Code Playgroud)

问题是我被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"
Run Code Online (Sandbox Code Playgroud)

这里有几件令我恼火的事情:

  • 有两个地方正常表达式似乎正在呼唤使用.这种拆分的Python方式是什么?
  • 我确保在字符串的两边剥去空白区域,然后重写字符串.这样,我不必多次进行剥离.但是,我正在重写字符串,我理解这是一个非常低效的Python操作.处理此问题的Python方法是什么?
  • 最后,我的算法看起来很像我的Perl算法,这似乎说我让Perl的想法妨碍了.我的代码应该如何用Python构建?

我一直在阅读各种在线教程,他们帮助我理解语法,但对处理语言本身的方式并不多 - 特别是那些倾向于用另一种语言思考的人.

我的问题:

  • 我应该使用正则表达式吗?或者,还有另一个更好的方法来处理这个问题吗?
  • 我的编码逻辑是否正确?我该如何考虑解析这个文件?

Spe*_*bun 5

Python包含一个ini解析库.如果你想构建一个库来解析ini文件,那么你正在寻找一个真正的解析器.正则表达式不会削减它,使用PLY或钩在flex/bison C解析器中.还可以使用其他python解析资源.

Lexers会为您处理所有文本消耗和树构造,因为它是一个容易出现程序员错误的机械任务.IE本节:

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";
    }

}
Run Code Online (Sandbox Code Playgroud)

由词法分析器创建,您只需要定义正确的正则表达式.解析器从词法分析器中提取标记,并确定它们是否适合允许的标记模式.那是:

[<type> <description>]
<parameter> = <value>
Run Code Online (Sandbox Code Playgroud)

定义这些令牌,然后定义如何适合.其他所有东西都融合在一起.对于那些认为你可以通过快速循环和一些正则表达式做得更好的人,我建议你阅读Lex&Yacc,第二版.

对于我用PLY写的示例解析器,请转到此处.它解析了一个"jetLetter"文件,它只是groff/troff的一种方言.


tjv*_*jvr 5

虽然我不认为这是您的意图,但文件格式看起来与 Python 的内置ConfigParser模块非常相似。有时已经为您提供了最“Pythonic”的方式。(:

更直接地回答你的问题:正则表达式可能是一个很好的方法。否则,你可以尝试更基本的(和不太健壮的)

(parameter, value) = line.split('=')
Run Code Online (Sandbox Code Playgroud)

如果该行不包含一个或多个 '=' 字符,这将引发错误。您可能想先用'=' in line.

还:

line.find("[") == 1
Run Code Online (Sandbox Code Playgroud)

可能更好地替换为

line.startswith("[")
Run Code Online (Sandbox Code Playgroud)

希望有所帮助(: