[英]Regex to follow pattern except between braces
我很难找出一个干净的正则表达式(在 Javascript 实现中),它将尽可能多地捕获一条线,因为它可以遵循一个模式,但是大括号内的任何东西都不需要遵循这个模式。 我不确定最好的解释方式,除了举例:
例如:假设模式是,行必须以 0 开头,在任何地方以 0 结尾,但只允许其间有 1、2 或 3 的序列,所以我使用^(0[123]+0)
。 这应该匹配字符串的第一部分:
0213123123130 012312312312303123123 01231230123123031230 etc.
但我希望能够在大括号之间插入{gibberish}
并让正则表达式允许它破坏模式。 即,忽略花括号的模式和里面的所有内容,但仍然捕获包括{gibberish}
在内的完整字符串。 所以这将以粗体捕获所有内容:
01232231{whatever 3 gArBaGe? I want.}121{foo}2310312{bar}3120123
即使模式正确,大括号内的 0 也不会过早结束捕获。
01213123123123{21310030123012301}31231230123
编辑:现在,我知道我可以做类似^0[123]*?(?:{.*})*?[123]*?0
的事情吗? 但这只有在有一组大括号时才有效,现在我必须复制我的[123]
模式。 随着[123]
模式变得越来越复杂,让它在正则表达式中出现不止一次开始变得非常难以理解。 最好的正则表达式技巧之类的东西似乎很有希望,但我不知道如何在这里应用它。 使用疯狂的环视似乎是现在唯一的方法,但我希望有一种更清洁的方法。
由于您已指定要包括垃圾在内的整个匹配项,因此您可以使用^0([123]+(?:{[^}]*}[123]*)*)0
并使用 $1 来获取部分在 0 之间,或 $0 以获得匹配的所有内容。
https://regex101.com/r/iFSabs/3
以下是正则表达式如何工作的概要:
^
将匹配锚定在行首0
匹配文字零字符([123]+(?:{[^}]*}[123]*)*)
是一个捕获组,它捕获其中的所有内容。
[123]+
匹配1
、 2
或3
的一个或多个实例(?:{[^}]*}[123]*)*
是一个非捕获组。 即它将成为比赛的一部分,但不会有 $# 用于替换或比赛。
{[^}]*}
匹配文字{
后跟任意数量的非}
字符后跟 }[123]*
匹配1
、 2
或3
的零个或多个实例此正则表达式背后的过程称为展开循环。 http://www.softec.lu/site/RegularExpressions/UnrollingTheLoop给出了很好的描述。 (有一些错字修复)
展开循环技术是基于这样一个假设,即在大多数情况下,您会 [知道] 在 [重复] 交替中,哪种情况应该是最常见的,哪种情况是例外的。 我们将第一个称为正常情况,将第二个称为特殊情况。 展开循环技术的一般语法可以写成:
正常*(特殊正常*)*
这可能意味着类似,匹配正常情况,如果你找到一个特殊情况,匹配它而不是再次匹配正常情况。 [你会]注意到这个语法的一部分可能[潜在地]导致超线性匹配。
使用 Regex#test 和 Regex#match 的示例:
const strings = [ '0213123123130', '012312312312303123123', '01231230123123031230', '01213123123123{21310030123012301}31231230123', '01212121{hello 0}121312', '012321212211231{whatever 3 gArBaGe? I want.}1212313123120123', '012321212211231{whatever 3 gArBaGe? I want.}121231{extra garbage}3123120123', ]; const regex = /^0([123]+(?:{[^}]*}[123]*)*)0/ console.log('tests') console.log(strings.map(string => `'${string}': ${regex.test(string)}`)) console.log('matches'); let matches = strings.map((string) => regex.exec(string)).map((match) => (match? match[1]: undefined)); console.log(matches);
Robo Robok 的答案是 go 如果您只想保留非支撑部分,尽管使用稍微不同的正则表达式( {[^}]*}
)以获得更高的性能。
反过来呢? 检查删除了卷曲标签的字符串:
const string = '012321212211231{whatever 3 gArBaGe? I want.}1212313123120123{foo}123';
const stringWithoutTags = string.replace(/\{.*?\}/g, '');
const result = /^(0[123]+0)/.test(stringWithoutTags);
您说您需要捕获所有内容,包括乱码,所以我认为像这样的简单模式应该可以工作:
^(0(?:[123]|{.+?})+0)
这允许以 0 开头的字符串,然后是任何模式字符(1、2 或 3)或{ gibberish }
部分之一,并允许重复处理多个乱码部分,最后它必须以一个 0。
你可能会使用
^0[123]*(?:{[^{}]*}[123]*)*0
^
字符串开头0
匹配一个零[123]*
匹配 0+ 次 1、2 或 3(?:
非捕获组
{[^{}]*}[123]*
匹配从开始到结束}
后跟 0+ 1、2 或 3)*
关闭组并重复 0+ 次0
匹配一个零
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.