15

我正在尝试在 Python (2.7) 中使用详细的正则表达式。如果这很重要,我只是想让它更容易回去,并在未来的某个时候更清楚地理解这个表达。因为我是新手,所以我首先创建了一个紧凑的表达式,以确保我得到了我想要的。

这是紧凑的表达式:

test_verbose_item_pattern = re.compile('\n{1}\b?I[tT][eE][mM]\s+\d{1,2}\.?\(?[a-e]?\)?.*[^0-9]\n{1}')

它按预期工作

这是详细表达式

verbose_item_pattern = re.compile("""
\n{1}       #begin with a new line allow only one new line character
\b?       #allow for a word boundary the ? allows 0 or 1 word boundaries \nITEM or \n  ITEM
I        # the first word on the line must begin with a capital I
[tT][eE][mM]  #then we need one character from each of the three sets this allows for unknown case
\s+       # one or more white spaces this does allow for another \n not sure if I should change it
\d{1,2}    # require one or two digits
\.?        # there could be 0 or 1 periods after the digits 1. or 1
\(?        # there might be 0 or 1 instance of an open paren
[a-e]?      # there could be 0 or 1 instance of a letter in the range a-e
\)?         # there could be 0 or 1 instance of a closing paren
.*          #any number of unknown characters so we can have words and punctuation
[^0-9]     # by its placement I am hoping that I am stating that I do not want to allow strings that end with a number and then \n
\n{1}     #I want to cut it off at the next newline character
""",re.VERBOSE)

问题是当我运行详细模式时出现异常

Traceback (most recent call last):
File "C:/Users/Dropbox/directEDGAR-Code-Examples/NewItemIdentifier.py", line 17, in <module>
 """,re.VERBOSE)
 File "C:\Python27\lib\re.py", line 190, in compile
  return _compile(pattern, flags)
 File "C:\Python27\lib\re.py", line 242, in _compile
 raise error, v # invalid expression
 error: nothing to repeat

恐怕这会很愚蠢,但我无法弄清楚。我确实采用了我的详细表达式并逐行压缩它,以确保压缩版本与详细版本相同。

错误消息指出没有什么可重复的?

4

2 回答 2

18
  • 在定义正则表达式模式时,使用原始字符串文字是一个好习惯。许多正则表达式模式使用反斜杠,并且使用原始字符串文字将允许您编写单个反斜杠,而不必担心 Python 是否会将您的反斜杠解释为具有不同的含义(并且在这些情况下必须使用两个反斜杠)。

  • \b?不是有效的正则表达式。这是说 0 或 1 字边界。但要么你有一个单词边界,要么你没有。如果你有一个单词边界,那么你有 1 个单词边界。如果您没有单词边界,那么您有 0 个单词边界。所以\b?(如果它是有效的正则表达式)总是正确的。

  • 正则表达式区分字符串的结尾和行的结尾。(一个字符串可能由多行组成。)

    • \A仅匹配字符串的开头。
    • \Z仅匹配字符串的结尾。
    • $匹配字符串的结尾,以及 re.MULTILINE 模式下的行尾。
    • ^匹配字符串的开头,以及 re.MULTILINE 模式下的行开头。

import re
verbose_item_pattern = re.compile(r"""
    $            # end of line boundary
    \s{1,2}      # 1-or-2 whitespace character, including the newline
    I            # a capital I
    [tT][eE][mM] # one character from each of the three sets this allows for unknown case
    \s+          # 1-or-more whitespaces INCLUDING newline
    \d{1,2}      # 1-or-2 digits
    [.]?         # 0-or-1 literal .
    \(?          # 0-or-1 literal open paren
    [a-e]?       # 0-or-1 letter in the range a-e
    \)?          # 0-or-1 closing paren
    .*           # any number of unknown characters so we can have words and punctuation
    [^0-9]       # anything but [0-9]
    $            # end of line boundary
    """, re.VERBOSE|re.MULTILINE)

x = verbose_item_pattern.search("""
 Item 1.0(a) foo bar
""")

print(x)

产量

<_sre.SRE_Match object at 0xb76dd020>

(表示有匹配)

于 2012-12-13T02:41:56.173 回答
2

正如评论中所说,即使使用三引号,您也应该转义反斜杠或使用原始字符串。

verbose_item_pattern = re.compile(r"""
...
于 2012-12-13T02:57:59.203 回答