正则表达式忽略已经声明的变量初始化

Regex to ignore variable initializations that have already been declared

我需要一个正则表达式,如果令牌的一部分之前已经被捕获,它会忽略令牌。

例子

var bold, det, bold=6, sum, k

这里,bold=6应该被忽略,因为bold已经被捕获了。 此外,var 必须在任何匹配发生之前出现,最后一个标记 k 后面不应跟逗号。只有 var 中的变量和最后一个标记 k 后应跟一个逗号。

另一个例子

var bold=6, det, bold, sum, k

这里,det后面的bold应该忽略,因为bold=6已经被捕获了。

我尝试使用这种模式 (?:\bvar\b|\G)\s*(\w+)(?:,|$),但它不会忽略重复的内容。

你可以调整你的正则表达式到这个负前瞻:

(?:\bvar\b|\G)\s*(?:(\w+)(?!.*\b\b)(?:=\w+)?|\S+)(?:,|\bk\b)

RegEx Demo

与其跟踪它已经匹配的内容,不如在字符串的其余部分后跟一个单词时跳过匹配。

这里 (?!.*\b\b) 是一个 negative lookahead 如果在输入的 RHS 上找到相同的词,它将避免匹配一个词。 </code> 是匹配词的反向引用。</p> <p><strong>正则表达式分解:</strong></p> <pre><code>(?:\bvar\b|\G) # match text var or \G \s* # match 0 more spaces (?: # start non-capturing group (\w+)(?!.*\b\b) # match a word if same word is found in rest of the input (?:=\w+)? # followed by optional = and some value | # regex alternation \S+ # OR match 1 or more non-space character ) # close non-capturing group (?:,|\bk\b) # match a comma or k

取决于您需要获取哪些信息,您可以尝试使用:

  1. 仅在 Java 中有效的解决方案将为您提供变量名称并开始 和结束 idices:

    (?<=var.{0,999})(?<!=)(?!var\b)\b(?<var>\w+)\b(?<!var.{1,999}(?=\k<var>).{1,999}(?=\k<var>).{1,999})
    

    RegexPlanet Demo

    它使用了 Java 正则表达式的丑陋但非常有效的功能:间隔 (x{min,max}) 回顾。只要你使用间隔 最小和最大长度,您可以在 Java 正则表达式中使用它。所以与其 .* 的你可以使用例如 .{0,999}。如果有它会失败 需要比 999 更多的字符,你可以使用更大的数字,但我 认为在这个cese中没有必要。命名组 <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。

  1. 如果只需要变量名,可以使用:

    (?<=var\s|\G,\s)(?<var>\w+)(?=,|$)|(?<=var\s|\G,\s)(?<initialized>[^,\n]+)
    

    DEMO

    获取不重复的变量名。但如果你想 start/end 个索引,它将捕获到组中第二次出现的 重复的变量名。