正则表达式忽略已经声明的变量初始化
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)
与其跟踪它已经匹配的内容,不如在字符串的其余部分后跟一个单词时跳过匹配。
这里 (?!.*\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
取决于您需要获取哪些信息,您可以尝试使用:
仅在 Java 中有效的解决方案将为您提供变量名称并开始
和结束 idices:
(?<=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 更多的字符,你可以使用更大的数字,但我
认为在这个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。
如果只需要变量名,可以使用:
(?<=var\s|\G,\s)(?<var>\w+)(?=,|$)|(?<=var\s|\G,\s)(?<initialized>[^,\n]+)
获取不重复的变量名。但如果你想
start/end 个索引,它将捕获到组中第二次出现的
重复的变量名。
我需要一个正则表达式,如果令牌的一部分之前已经被捕获,它会忽略令牌。
例子
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)
与其跟踪它已经匹配的内容,不如在字符串的其余部分后跟一个单词时跳过匹配。
这里 (?!.*\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
取决于您需要获取哪些信息,您可以尝试使用:
仅在 Java 中有效的解决方案将为您提供变量名称并开始 和结束 idices:
(?<=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 更多的字符,你可以使用更大的数字,但我 认为在这个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。
如果只需要变量名,可以使用:
(?<=var\s|\G,\s)(?<var>\w+)(?=,|$)|(?<=var\s|\G,\s)(?<initialized>[^,\n]+)
获取不重复的变量名。但如果你想 start/end 个索引,它将捕获到组中第二次出现的 重复的变量名。