python - 当此字符串中的行尾有数字时,为什么此正则表达式不排除该行

标签 python regex

我正在尝试扫描文档并确定文档部分的开始和结束位置。有时,文档有一个目录,其中列出了页码我不想捕获 TOC,因为它没有标识文档的一部分。一段时间以来,我一直在搞乱这个问题,并且被困在某些事情上。我似乎无法避免使用行号从目录中捕获行

这是正则表达式

verbose_item_pattern_3 = re.compile(r"""
  ^            # begin match at newline
  \t*          # 0-or-more tabspace
  [ ]*         # 0-or-more blank space
  I            # a capital I
  [tT][eE][mM] # one character from each of the three sets this allows for unknown case
  \t*          # 0-or-more tabspace
  [ ]*         # 0-or-more blankspace
  \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]
  $           # 1 newline character
  """, re.VERBOSE|re.MULTILINE)

这是我不想捕获的一行示例

test_string='\nItem 6.       TITLE ITEM 6..................................................25\n'

这是我想要捕捉的一个例子

test_string='\nItem 6.       TITLE ITEM 6 maybe other words here who knows  \n'

但是当我运行的时候

re.findall(verbose_item_pattern_3,test_string)

结果是

['Item 6.       TITLE ITEM 6..................................................25\n']

现在对我来说有趣的是,如果我的测试字符串是这个

test_string='PART I\nItem 1.       TITLE ITEM 1...................................................1\nItem 2.       TITLE ITEM 2..................................................21\n'

然后用 re.findall(verbose_item_pattern_3,test_string)

结果更接近我想要的但仍然不正确

['Item 2.       TITLE ITEM 2..................................................21\n']

不应该有任何捕获

最佳答案

你的正则表达式匹配是因为三件事。

  1. 大部分是可选的,所以很不明确
  2. 有一个 .* 吃掉了整行,所以你的最后一个条件 [^0-9] 永远不会成立,那是因为:<
  3. 换行符本身满足[^0-9],所以[^0-9]可以成功匹配,即使行以数字结尾。

最小的变化是在最后使用负面回顾:

verbose_item_pattern_3 = re.compile(r"""
  ^            # start-of-line
  \t*          # 0-or-more tabspace
  [ ]*         # 0-or-more blank space
  I            # a capital I
  [tT][eE][mM] # one character from each of the three sets this allows for unknown case
  \t*          # 0-or-more tabspace
  [ ]*         # 0-or-more blankspace
  \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
  $            # end-of-line
  (?<![0-9])   # NOT preceded by a decimal digit (via look-behind)
  """, re.VERBOSE|re.MULTILINE)

请注意,^$ 实际上都不匹配换行符。它们匹配 紧接在 (^) 或 ($) 换行符之前的位置。换行符本身永远不是匹配的一部分。

出于这个原因,我已将他们的注释更改为更精确的 start-of-lineend-of-line

另请注意,即使在 $ 之后我也可以应用负向回顾。这样做有助于防止回溯,使正则表达式更快。<​​/p>

关于python - 当此字符串中的行尾有数字时,为什么此正则表达式不排除该行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13883257/

相关文章:

regex - 确保正则表达式与 Swift 正则表达式匹配整个字符串

python - Plotly:如何使用 go.Figure 和 go.Scatter 为每个 y 误差条设置单独的颜色?

python - 装饰 lxml.etree._Element 方法

python - 如何搜索一列并用找到的内容填充另一列?

python - 在同一类的方法中使用类/静态方法作为默认参数值

javascript - 正则表达式字符串 URL

java - 从字符串中删除自定义标签,然后格式化其内容

Python、PyDot 和决策树

javascript - 在表单输入中指定逗号后的最大长度

regex - 读取文件并修改它