Python正则表达式 - 模式匹配

时间:2012-10-25 15:29:57

标签: python regex python-2.7

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

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

"(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个非空格字符以及行尾。

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

3 个答案:

答案 0 :(得分:4)

$^这不起作用。 $是行尾(换行符之前),^是行的开头(换行符之后)。但是换行符是一个字符(或两个),而不是提升正则表达式引擎的位置。所以$^尝试匹配相同的位置,只有当它们是空行的结尾和开头时才会发生 - 即使然后将它们按此顺序排列也会产生很大的误导。如果你想确保它们之间只有一个换行符,请尝试:

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

然而,正如嘲笑者指出评论一样,以下\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 :(得分:1)

我认为你对大写字母和特定数量的空格之类的东西过于具体(你的示例字符串在开头时甚至没有空格)。我主要只是坚持*和+,除非我正在寻找非常具体的东西。正如另一个答案所指出的那样,$是整个记录(字符串)的结尾,而不是行尾。换行符或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')

答案 2 :(得分:1)

我真的在想这个。以下是我根据提供的答案提出的解决方案:

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

'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*'找到所有网址 - 这会返回我想要的所有结果以及列表末尾的额外'http://somewebsite.com'

然后我将这些列表压缩在一起,排除了最后一个列表的最后一个元素,我基本上得到了我首先要查找的结果。