这是我第一次使用正则表达式进行模式匹配 任何帮助表示赞赏。
我正在尝试在字符串中搜索以下子字符串:
"(TPU 1-999)
http://somewebaddress.com"
我希望将TPU
,1-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个非空格字符以及行尾。
这种模式现在不行,但我是朝着正确的方向前进吗?
答案 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'
。
然后我将这些列表压缩在一起,排除了最后一个列表的最后一个元素,我基本上得到了我首先要查找的结果。