正则表达式在两个字符串(它们是变量)之间提取

Posted

技术标签:

【中文标题】正则表达式在两个字符串(它们是变量)之间提取【英文标题】:Regex to extract between two strings (which are variables) 【发布时间】:2015-06-21 18:51:36 【问题描述】:

我希望使用正则表达式来提取出现在两个字符串之间的文本。我知道如果我每次都想在相同的字符串之间提取(以及无数个问题,例如Regex matching between two strings?),但我想使用发生变化的变量来做到这一点,并且它们本身可能包含正则表达式中的特殊字符。 (我想要任何特殊字符,例如 * 被视为文本)。

例如,如果我有:

text = "<b*>Test</b>"
left_identifier = "<b*>"
right_identifier = "</b>

我想创建将导致以下代码运行的正则表达式代码:

re.findall('<b\*>(.*)<\/b>',text)

&lt;b\*&gt;(.*)&lt;\/b&gt;部分,我不知道怎么动态创建。

【问题讨论】:

您可能需要考虑一个非贪婪的量词:(.*?) 这匹配尽可能少的字符。因此,对于像“left_identifierstuffright_identifier left identifiermore stuffright_identifier”这样的字符串,您只会在两个单独的匹配项中找到“stuff”和“more stuff”,而不是“stuffright_identifier” left identifiermore stuff" 在一场比赛中。 谢谢 - 好地方 - 你是对的 - 我的意思是非贪婪量词! 请注意使用正则表达式解析 html is not recommended。您应该使用 HTML 解析器(无论 Python 中的 Nokogiri 是什么),然后从相应的标签中提取文本。 @Phrogz - 示例已简化 - 通常不基于 html 标签进行解析(尽管需要能够处理它们,因为它们会裁剪到我输入的文本中)。 【参考BeautifulSoup是python中等价的html解析器】。 【参考方案1】:

你可以这样做:

import re
pattern_string = re.escape(left_identifier) + "(.*?)" + re.escape(right_identifier)
pattern = re.compile(pattern_string)

转义函数会自动转义特殊字符。例如:

>>> import re
>>> print re.escape("<b*>")
\<b\*\>

【讨论】:

还请注意(.*?) 而不是(.*),这是非贪婪捕获。这可能是您想要的。 我尝试使用 "PRIMARY KEY(\n" 作为左侧标识符和 ")" 作为右侧标识符执行上述操作,但对我不起作用。我想从下面获取所有主键: PRIMARY KEY (ROLE_ID) USING INDEX APP_ROLES.SR_PK ENABLE VALIDATE);【参考方案2】:

你需要re.escape标识符:

>>> regex = re.compile('(.*)'.format(re.escape('<b*>'), re.escape('</b>')))
>>> regex.findall('<b*>Text</b>')
['Text']

【讨论】:

【参考方案3】:

正则表达式开始它的生命就像一个字符串,所以left_identifier + text + right_identifier 并在re.compile 中使用它

或者:

re.findall('(.*)'.format(left_identifier, right_identifier), text)

也可以。

如果变量中的字符串包含带有re.escape 的正则表达式元字符,并且您不希望元字符被这样解释,则需要对它们进行转义:

>>> text = "<b*>Test</b>"
>>> left_identifier = "<b*>"
>>> right_identifier = "</b>"
>>> s='(.*?)'.format(*map(re.escape, (left_identifier, right_identifier)))
>>> s
'\\<b\\*\\>(.*?)\\<\\/b\\>'
>>> re.findall(s, text)
['Test']

附带说明,str.partition(var) 是执行此操作的另一种方法:

>>> text.partition(left_identifier)[2].partition(right_identifier)[0]
'Test'

【讨论】:

【参考方案4】:

我知道您实际上想要一个正则表达式解决方案,但考虑到we all have taken oath not to,我真的想知道正则表达式是否是正确的工具。在解析 html 字符串时,我总是建议回退到beautifulsoup

>>> import bs4
>>> bs4.BeautifulSoup('<b*>Text</b>').text
u'Text'

【讨论】:

以上是关于正则表达式在两个字符串(它们是变量)之间提取的主要内容,如果未能解决你的问题,请参考以下文章

使用正则表达式仅提取两个特定标记之间的数字

BigQuery 正则表达式提取两个子字符串之间的字符串

正则表达式获得两个字符串之间的内容

正则表达式:获取 AWS Redshift 中两个字符串之间的值

使用正则表达式提取字符串 - str_extract、stringr、regex

正则表达式截取两个指定字符串之间的内容都有哪些?