Python,递归地应用正则表达式负先行
Python, applying regex negative lookahead recursivly
在 python 中,我试图通过将用户定义的正则表达式解析为自定义正则表达式来实现它。然后将此自定义正则表达式应用于 space 分隔的字符串。这个想法是在第二列 上应用用户正则表达式而不使用 for 循环 .
Stream //streams/sys_util mainline none 'sys_util'
Stream //streams/gta mainline none 'gta'
Stream //streams/gta_client development //streams/gta_cdevelop 'gta_client'
Stream //streams/gta_develop development //streams/gta 'gta_develop'
Stream //streams/gta_infrastructure development //streams/gta 'gta_infrastructure'
Stream //streams/gta_server development //streams/gta_cdevelop 'gta_server'
Stream //streams/0222_ImplAlig1.0 task none '0222_ImplAlig1.0'
Stream //streams/0377_kzo_the_wart task //streams/applications_int '0377_tta'
预期输出应该是
//streams/gta
//streams/gta_client
//streams/gta_develop
//streams/gta_infrastructure
//streams/gta_server
这是我的代码,
import re
mystring = "..."
match_rgx = r'Stream\s(\/\/streams\/gta.*)(?!\s)'
result = re.findall(match_rgx, mystring, re.M)
注意: 第一个括号内的表达式无法更改(因为它是根据用户输入解析的)因此 \/\/streams\/gta.*
必须保持原样。
我怎样才能改进负面前瞻以获得预期的结果?
在 https://regex101.com/ 上测试,这应该对所有第二列起作用:
(?:\w+\s([^\s]+)\s.*[\n|\n\r]*)
这仅适用于 GTA 第 2 列:
(?:\w+\s(\/\/streams\/gta[^\s]*)\s.*[\n|\n\r]*)
一行就像(第二列):
\w+\s([^\s]+)\s.*
Gta 仅适用于 1 行:
\w+\s(\/\/streams\/gta[^\s]*)\s.*
您可以使用:
match_rgx = 'Stream\s(//streams/gta.*?)\s'
result = re.findall(match_rgx, mystring)
默认情况下,运算符 * 是贪婪的,因此它会尝试捕获尽可能多的文本(例如:“//streams/gta mainline none”将在没有 ? 的情况下进行匹配)。但是你只想要第二列,所以,用 ?您的运算符变为 non-greedy,并在第一次出现 \s ("//streams/gta") 时停在最小模式处。
希望这很清楚,如果不清楚,请查看文档 (https://docs.python.org/2/library/re.html#contents-of-module-re)。
顺便说一句,您不必转义 /,它不是特殊字符。
如果不使用 ^ 或 $.
,则使用 re.M 标志是没有用的
编辑:由于你的编辑,如果你不想赶上发展,一些信息就变得无用了。
编辑 2:没看到你不想更改模式。在这种情况下,只需执行:
match_rgx = 'Stream\s(\/\/streams\/gta.*?)\s'
Edit3:查看评论。
在 python 中,我试图通过将用户定义的正则表达式解析为自定义正则表达式来实现它。然后将此自定义正则表达式应用于 space 分隔的字符串。这个想法是在第二列 上应用用户正则表达式而不使用 for 循环 .
Stream //streams/sys_util mainline none 'sys_util'
Stream //streams/gta mainline none 'gta'
Stream //streams/gta_client development //streams/gta_cdevelop 'gta_client'
Stream //streams/gta_develop development //streams/gta 'gta_develop'
Stream //streams/gta_infrastructure development //streams/gta 'gta_infrastructure'
Stream //streams/gta_server development //streams/gta_cdevelop 'gta_server'
Stream //streams/0222_ImplAlig1.0 task none '0222_ImplAlig1.0'
Stream //streams/0377_kzo_the_wart task //streams/applications_int '0377_tta'
预期输出应该是
//streams/gta
//streams/gta_client
//streams/gta_develop
//streams/gta_infrastructure
//streams/gta_server
这是我的代码,
import re
mystring = "..."
match_rgx = r'Stream\s(\/\/streams\/gta.*)(?!\s)'
result = re.findall(match_rgx, mystring, re.M)
注意: 第一个括号内的表达式无法更改(因为它是根据用户输入解析的)因此 \/\/streams\/gta.*
必须保持原样。
我怎样才能改进负面前瞻以获得预期的结果?
在 https://regex101.com/ 上测试,这应该对所有第二列起作用:
(?:\w+\s([^\s]+)\s.*[\n|\n\r]*)
这仅适用于 GTA 第 2 列:
(?:\w+\s(\/\/streams\/gta[^\s]*)\s.*[\n|\n\r]*)
一行就像(第二列):
\w+\s([^\s]+)\s.*
Gta 仅适用于 1 行:
\w+\s(\/\/streams\/gta[^\s]*)\s.*
您可以使用:
match_rgx = 'Stream\s(//streams/gta.*?)\s'
result = re.findall(match_rgx, mystring)
默认情况下,运算符 * 是贪婪的,因此它会尝试捕获尽可能多的文本(例如:“//streams/gta mainline none”将在没有 ? 的情况下进行匹配)。但是你只想要第二列,所以,用 ?您的运算符变为 non-greedy,并在第一次出现 \s ("//streams/gta") 时停在最小模式处。
希望这很清楚,如果不清楚,请查看文档 (https://docs.python.org/2/library/re.html#contents-of-module-re)。
顺便说一句,您不必转义 /,它不是特殊字符。 如果不使用 ^ 或 $.
,则使用 re.M 标志是没有用的编辑:由于你的编辑,如果你不想赶上发展,一些信息就变得无用了。
编辑 2:没看到你不想更改模式。在这种情况下,只需执行:
match_rgx = 'Stream\s(\/\/streams\/gta.*?)\s'
Edit3:查看评论。