如果之前已经捕获了令牌的一部分,我需要一个忽略令牌的正则表达式。
示例
var bold, det, bold=6, sum, k
此处,bold=6
应该被忽略,因为已经捕获了bold
。
此外,在发生任何匹配之前必须存在var
,最后一个标记k
不应该跟逗号。只有var
和最后一个标记k
中的变量后面应加一个逗号。
另一个例子
var bold=6, det, bold, sum, k
此处,bold
后面的det
应被忽略,因为bold=6
已被捕获。
我尝试使用这种模式(?:\\bvar\\b|\\G)\\s*(\\w+)(?:,|$)
,但它并没有忽略重复的内容。
答案 0 :(得分:1)
你可以用一个负向前瞻来调整你的正则表达式:
cd test
npm install
如果在字符串的其余部分跟随一个单词,它将跳过匹配单词,而不是跟踪它已经匹配的内容。
此处(?:\bvar\b|\G)\s*(?:(\w+)(?!.*\b\1\b)(?:=\w+)?|\S+)(?:,|\bk\b)
是否定前瞻,如果在输入的RHS上找到相同的单词,将避免匹配单词。 (?!.*\b\1\b)
是匹配词的反向引用。
RegEx分手:
\1
答案 1 :(得分:1)
取决于您可以尝试使用哪些信息:
仅在Java中工作的解决方案,将为您提供变量名称并启动 和结束的错误:
(?<=var.{0,999})(?<!=)(?!var\b)\b(?<var>\w+)\b(?<!var.{1,999}(?=\k<var>).{1,999}(?=\k<var>).{1,999})
它使用Java正则表达式的丑陋但非常有效的特性:间隔
(x{min,max}
)在后面。只要你使用间隔
最小和最大长度,您可以在Java正则表达式中使用它。所以与其
.*
您可以使用.{0,999}
。如果有的话会失败
需要比999更多的char,你可以使用更大的数字,但我
认为在这个问题上没有必要。命名组<var>
在此处是可选的,您可以使用普通组在代码中添加它。
Java实现:
public class Test{
public static void main(String[] args){
String test = "var bold, det, bold=6, sum, k\n" +
"var foo=6, abc, foo, xyz, k";
Matcher matcher = Pattern.compile("(?<=var.{0,999})(?<!=)(?!var)\\b(?<var>\\w+)\\b(?<!var.{1,999}(?=\\k<var>).{1,999}(?=\\k<var>).{1,999})").matcher(test);
while(matcher.find()){
System.out.println(matcher.group("var") + "," + matcher.start("var") + "," + matcher.end("var"));
}
}
}
带输出的(变量名,起始索引,结束索引):
bold,4,8
det,10,13
sum,23,26
k,28,29
foo,34,37
abc,41,44
xyz,51,54
k,56,57
正则表达式的解释:
(?<=var.{0,999})
- 必须以文字var
开头,后跟任意(?<!=)
- 不应以等号开头,以避免将变量名称和值匹配为不同的匹配项,(?!var\b)
- var
字后面跟不能,以避免匹配这个字,\b(?<var>\w+)\b
- 单独的单词,被捕获到<var>
组,(?<!var.{1,999}(?=\k<var>).{1,999}(?=\k<var>).{1,999})
- 匹配的单词前面不能有var
字后跟一些字符,包括捕获的字,后跟一些字符,再次包含捕获的字,但正如我所写的那样,它只适用于Java。
如果只需要变量名称,可以使用:
(?<=var\s|\G,\s)(?<var>\w+)(?=,|$)|(?<=var\s|\G,\s)(?<initialized>[^,\n]+)
获取没有重复的变量名称。但如果你想 开始/结束索引,它将捕获到组的第二次出现 重复的变量名称。