【问题标题】:Python Regular Expression - Pattern MatchingPython 正则表达式 - 模式匹配
【发布时间】:2012-10-25 15:29:56
【问题描述】:

这是我第一次使用正则表达式进行模式匹配,所以 任何帮助表示赞赏。

我正在尝试在字符串中搜索以下子字符串:

"(TPU 1-999)
http://somewebaddress.com"

我想将TPU1-999 和链接保留为单独的子字符串。

这是我正在使用的模式:

^\s{3}\(([AEINPRSTUW]{3})\s(\d{1,3}.\d{2,5})\)$^\s{3}(http+\s{1,100})$

我会分解来解释我的推理

^\s{3} - 字符串开头(或本例中的行),后跟 3 个空格

\( - 左括号

([AEINPRSTUW]{3}) - 括号中任何字母的 3 个实例,TPU 是一个例子

\s(\d{1,3}.\d{2,5}) - 一个空格,然后是 1-3 个数字,由 2-5 个数字之间的任意字符分隔

\)$ - 右括号,行尾

^\s{3} - 下一行开头后跟三个空格

(http+\s{1,100})$ - 字符“http”后跟 1 到 100 个非空白字符,以及行尾。

这种模式现在行不通,但我是否朝着正确的方向前进?

【问题讨论】:

  • 那些" 真的是你的字符串的一部分吗?您要匹配的这三个空间在哪里?

标签: python regex python-2.7


【解决方案1】:

$^ 这行不通。 $ 是行尾(换行之前),^ 是行开头(换行之后)。但是换行符是一个字符(或两个),同时不推进正则表达式引擎的位置。所以$^ 尝试匹配相同的位置,这只有在它们是空行的结尾和开头时才会发生——即使这样将它们按此顺序排列也会产生很大的误导。如果您想确保它们之间恰好有一个换行符,请尝试以下操作:

^\s{3}\(([AEINPRSTUW]{3})\s(\d{1,3}.\d{2,5})\)$(\r\n?|\n)^\s{3}(http+\S{1,100})$

但是,正如 ridgerunner 指出的评论,以下 \s{3} 可以匹配(最多 3 个)更多换行符,因为它们也是空格。

另请注意,. 作为数字的分隔符可能不是最好的主意。至少,使用非数字字符:

^\s{3}\(([AEINPRSTUW]{3})\s(\d{1,3}\D\d{2,5})\)$(\r\n?|\n)^\s{3}(http+\S{1,100})$

另请注意,我已将您的最后一个 \s 更改为 \S(因为 \s 是空格,\S 是非空格)。

另外请注意,您向我们展示的字符串不包含您尝试匹配的那三个空格。因此,将它们设为可选(正如 CaptainMurphy 建议的那样)也可能会有所帮助:

^\s*\(([AEINPRSTUW]{3})\s(\d{1,3}\D\d{2,5})\)$(\r\n?|\n)^\s*(http+\S{1,100})$

而且由于我们已经匹配了换行符,我们还可以完全删除那里的那些锚点,它们不再有任何帮助:

^\s*\(([AEINPRSTUW]{3})\s(\d{1,3}\D\d{2,5})\)(\r\n?|\n)\s*(http+\S{1,100})$

【讨论】:

  • 非常感谢 - 一个巨大的帮助。
  • +1 但有几点...首先,从技术上讲,$^ 本身确实匹配空行(^$ 也是如此) - 多个相邻零宽度断言的顺序没关系(尽管你是正确的,在这个正则表达式的上下文中它永远不会匹配)。其次,(\r\n?|\n)\s* 不保证只有一个新行,因为\s* 匹配回车符和换行符。否则,很好的解释。
  • @ridgerunner,你当然是完全正确的!我将添加以澄清
【解决方案2】:

我认为您对大写字母和特定数量的空格等内容过于具体(您的示例字符串开头甚至没有空格)。我大多只是坚持 * 和 + 除非我正在寻找非常具体的东西。正如另一个答案指出的那样, $ 是整个记录(字符串)的结尾,而不是行尾。换行符或 CRLF 只是空格。不要将 \s 甚至 [^\s] 用于非空白,使用 \S。

ss="(TPU 1-999)\nhttp://something.com"
rr="^\s*\(([A-Z]+)\s+(\d+.\d+)\)\s+(http\S{1,100})$"
re.match(rr,ss).groups()
('TPU', '1-999', 'http://something.com')

【讨论】:

  • 非常感谢,确实帮了不少忙。
【解决方案3】:

我真的想多了。这是我根据提供的答案提出的解决方案:

这是我正在解析的字符串示例(从电子邮件的内容中提取):

'The writeboard named "10/26 newsletters (Pat)" has been created:\r\n\r\n (TPU 1000+)\r\n\r\n http://www.techproductupdate.com/resources/2313/splunk-app-for-vmware-delivers-insight-into-the-cloud\r\n\r\n (TIN 250+)\r\n\r\n http://www.techproductupdate.com/resources/2369/securing-mysql-databases\r\n\r\n (TPU 500+)\r\n\r\n http://www.techproductupdate.com/resources/2333/designing-a-data-protection-strategy-with-hp-lefthand-hp-storeonce-and-hp-tape\r\n\r\n- - -\r\nYou can visit the writeboard at:\r\n http://somewebsite.com\r\n'

所以我首先使用re.findall 来定位括号之间的所有内容,使用模式'\((?P<list>[A-Z]*)\s(?P<segments>.+)\)'

然后我使用re.findall 来定位所有使用模式'http\S*' 的URL - 这将返回我想要的所有结果,并在列表末尾添加额外的'http://somewebsite.com'

然后我只是将这些列表压缩在一起,不包括最后一个列表的最后一个元素,我基本上得到了我首先要寻找的结果。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-01
    相关资源
    最近更新 更多