我一直在寻找解决方法,但无法实现。我并不是完全的新手。
我需要获取由(包括)START和END分隔的文本,该文本不包含START。基本上,我找不到一种不使用高级功能来否定整个单词的方法。
示例字符串:
abcSTARTabcSTARTabcENDabc
期望的结果:
STARTabcEND
不好的结果:
STARTabcSTARTabcEND
我不能使用向后搜索的功能。我正在这里测试我的正则表达式:www.regextester.com
感谢任何建议。
我一直在寻找解决方法,但无法实现。我并不是完全的新手。
我需要获取由(包括)START和END分隔的文本,该文本不包含START。基本上,我找不到一种不使用高级功能来否定整个单词的方法。
示例字符串:
abcSTARTabcSTARTabcENDabc
期望的结果:
STARTabcEND
不好的结果:
STARTabcSTARTabcEND
我不能使用向后搜索的功能。我正在这里测试我的正则表达式:www.regextester.com
感谢任何建议。
试一下这个
START(?!.*START).*?END
在Regexr网站在线查看它。
(?!.*START)
是一个负向先行断言。它确保单词“START”没有跟在后面。
.*?
是非贪婪匹配,匹配所有字符直到下一个“END”,因为负向先行断言只是向前查找而不捕获任何内容(零长度断言)。
更新:
我再考虑了一下,上面的解决方案是匹配到第一个“END”。如果不想这样做(因为你要从内容中排除START),请使用贪婪版本。
START(?!.*START).*END
这将匹配到最后一个"END"。
START...END
对,这将失败。 (更准确地说,它只会在字符串中找到最后一个START...END
对。) - Tim PietzckerEND
之前还是之后(例如abcSTARTabcENDxyzSTART
),您的正则表达式将不会匹配到您期望的位置。 - vladrSTART(?:(?!START).)*END
这段代码将适用于任意数量的 START...END
成对出现。以下是Python演示:
>>> import re
>>> a = "abcSTARTdefENDghiSTARTjlkENDopqSTARTrstSTARTuvwENDxyz"
>>> re.findall(r"START(?:(?!START).)*END", a)
['STARTdefEND', 'STARTjlkEND', 'STARTuvwEND']
START
和END
之间的内容,可以使用以下方法:(?<=START)(?:(?!START).)*(?=END)
看这里:
>>> re.findall(r"(?<=START)(?:(?!START).)*(?=END)", a)
['def', 'jlk', 'uvw']
s
点匹配所有标志)。 - ridgerunnerSTART(([^S] | S * S [^ ST] | ST [^ A] | STA [^ R] | STAR [^ T]) *(S(T(AR?)?)?)?) END
。现代正则表达式有负断言,可以更优雅地实现此目的,但我理解您关于“向后搜索”的评论可能意味着您不能或不想使用此功能。START(([^ ES] | E * E [^ ENS] | EN [^ DS] | S * S [^ STE] | ST [^ AE] | STA [^ RE] | STAR [^ TE])*(S(T(AR?)?)?| EN?)?)END
。这在大多数文化中都会超过折磨阈值。SSTART
可以成为匹配的一部分(第二个S
将匹配 [^ T] 等)。我通过在 [^ ST]
中添加S
并在非可选的 S
之前添加 S *
来修复了此问题,以允许任意重复 S
。
(S(T(AR?)?)?)?
? - AturSams...(S(T(AR?)?)?)?...
,否则,你必须在 S
、ST
、STA
和 STAR
之后消耗字符...这太聪明了。 - AturSams(S(T(AR?)?)?)?
这部分,但我认为原因是否则你无法匹配像STARTSTAREND
这样的东西。 (S(T(AR?)?)?)?
让您干净地消耗任何直接出现在END
之前的STAR
子字符串。 - AturSamsSTAR
后面跟着的不是T
,我们允许它后面跟着某些东西,但就在结束分隔符之前,我们也允许它后面什么都没有。(在这种情况下使用“consume”有点奇怪,个人认为。) - tripleeeSTART(?:(?!START).)*?END
会更好,只会捕获一个紧随其后没有任何START
或END
之间的START
和END
。 我正在使用.NET,而Tim的解决方案也会匹配类似START END END
的表达式。 至少在我的个人情况下,这是不希望发生的。[编辑:我留下了这篇文章,以获取有关捕获组的信息,但我给出的主要解决方案是不正确的。
正如评论中指出的那样,将无法工作;我忘记了被忽略的字符不能被删除,因此您需要像...(?:START)((?:[^S]|S[^T]|ST[^A]|STA[^R]|STAR[^T])*)(?:END)
|STA(?![^R])|
这样的东西仍然允许该字符成为END的一部分,因此在类似STARTSTAEND的情况下失败;因此这显然是更好的选择;以下应显示使用捕获组的正确方法...
使用“零宽度负向先行断言”运算符“?”给出的答案,带有捕获组:(?:START)((?!.*START).*)(?:END)
,它使用$1捕获内部文本进行替换。如果您想捕获START和END标记,可以执行(START)((?!.*START).*)(END)
,其中$1=START $2=text,$3=END或通过添加/删除()
或?:
来进行各种其他排列。
这样,如果您要使用它进行搜索和替换,您可以执行类似于BEGIN$1FINISH的操作。因此,如果您从以下内容开始:
abcSTARTdefSTARTghiENDjkl
您将获得ghi
作为捕获组1,并且使用BEGIN$1FINISH进行替换将给您以下结果:
abcSTARTdefBEGINghiFINISHjkl
这将允许您仅在正确配对时更改START/END标记。
每个(x)
都是一个组,但我已经为除中间组之外的每个组放置了(?:x)
,以将其标记为非捕获组;我唯一没有使用?:
的是中间组;但是,如果您想移动它们或其他操作,也可以捕获BEGIN/END标记。
有关Java正则表达式的完整详细信息,请参见Java regex documentation。
abcSTARTabcENDabcSTARTabcENDabc
,你想要匹配两个吗? - Tim Pietzcker