在平衡字符内搜索特定文本(递归

给出以下(消毒)输入:

Return_t func() { Type cursorFeature(true); while (nDist derefenced, MACRO) != 0)) { bIsChanged = true; break; } memcpy(&var, &cursorFeature->dereferenced, sizeof(anotherType_t)); } } //more stuff } } 

我有以下正则表达式捕获使用Type后发生的循环

 Type.*\s*(\w*)[^}]*?(?:while|for)\s*\(.*?\n?.*?(\{(?>[^{}]|(?-1))*\}) 

https://regex101.com/r/Kr0zQq/3

我还有以下正则表达式,它捕获Type变量的特定用法:

 Type.*\s*(\w*)[\s\S]*?\K(?|\+\+) 

https://regex101.com/r/Kr0zQq/4

我的目标是以某种方式将这些结合起来,最好是组合成一个正则表达式(如果可能的话,我希望能够在VS内部进行搜索)。 鉴于递归正则表达式的性质,我不确定这是否可能……而且我怀疑它不是。 如果没有,那么在搜索数百个文件时不会失去文件名/数字上下文的聪明的东西会很棒。 我基本上需要文件名和行号。 上下文很棒,但不是必需的。

为了澄清,我想捕获cursorFeature因为它的类型为Type ,然后我想在"loop"{.....}搜索它的使用

编辑

只是关于我使用正则表达式解决这个问题的说明。 被搜索的代码超过一百万行,跨越由各种编译器编译并由多个构建系统构建的多个项目。 例如,使用宏和高级语言function意味着甚至VS Intellisense 经常错误地编写VS能够编译的代码。 和YCM(vim)一样。 因此,一个可能过于贪婪的正则表达式,即70%的误报是好的。 (由于缺少循环中变量使用的进一步发生,因为在那一点上通常很容易扫描其余部分。)然而,尝试使用“通用”PCRE作为单行进行这可能是愚蠢的。 🙂

如果匹配的变量名存在于以下循环中,则有三个选项可供查看。 首先是将(\1)添加到primefaces组并检查环境中是否存在此捕获组(如果可能):

 (?>(\1)|[^{}]|(?-2))* 

其次,你可以使用负前瞻来调整[^{}]的匹配过程:

 (?>(?!\1)[^{}]|(?-1))* 

但是如果你没有像我在评论中提供的演示中那样使得闭括号可选,它就会失败。

第三个更好的解决方法是使用动词(*ACCEPT) ,这会立即导致成功匹配的结束,而无需在正则表达式中进行进一步更改:

 (?>(\1)(*ACCEPT)|[^{}]|(?-2))* 

现场演示

要使用单个正则表达式执行此操作,需要使用Perl代码块
和条件的代码。

虽然接受的答案很好,但它无法validationType变量
将存在于平衡循环内。

这里的代码只是按原样存储Type变量的位置
在所有嵌套循环中找到。 它不会错过任何一个。

举个例子,我在一些地方播种了多个位置的数据集
循环,其他人的单一位置,另一个没有。

除了字符串中的位置之外,您如何定位取决于您。

Perl的

 use strict; use warnings; $/ = undef; my $data = ; my @vals; while ( $data =~ / (?{ @vals = () }) # Code block - Initialize @vals Type .* < .* > \s* ( \w+ ) # (1) [^}]*? (?: while | for ) \s* \( .*? (?: \r? \n )? .*? (? # (2 start) \{ (?> (? | \+\+ ) (?{ # Code block - Push capture position onto @vals push (@vals, pos()); }) | [^{}] | (?&core) )* \} ) # (2 end) (?(?{ # Code conditional - Fail this block (bypass) if didn't find any @vals == 0 }) (*SKIP) (*FAIL) ) /xg ) { print "\nfound '$1' at pos: "; for ( @vals ) { print $_ , ", "; } } __DATA__ Return_t func() { Type cursorFeature(true); while (nDist < 800) { Result1 = Example(&var, 0, cursorFeature); if (!(++cursorFeature).NoMoreRecords()) { if (!BLAH(blah) && (otherFunc(&var, &cursorFeature->derefenced, MACRO) != 0)) { bIsChanged = true; Result2 = Example(&var, 0, cursorFeature); break; } else Result3 = Example(&var, 0, cursorFeature); memcpy(&var, &cursorFeature->dereferenced, sizeof(anotherType_t)); } } //more stuff } // --------------------------------- Return_t func() { Type globeFeature(true); while (nDist < 800) { if (!(++globeFeature).NoMoreRecords()) { if (!BLAH(blah) && (otherFunc(&var, &penFeature->derefenced, MACRO) != 0)) { bIsChanged = true; break; } else memcpy(&var, &globeFeature->dereferenced, sizeof(anotherType_t)); } } } } // --------------------------------- Return_t func() { Type penFeature(true); while (nDist < 800) { if (!(++penFeature).NoMoreRecords()) { if (!BLAH(blah) && (otherFunc(&var, &penFeature->derefenced, MACRO) != 0)) { bIsChanged = true; Result = Example(&var, 0, penFeature); break; } else memcpy(&var, &penFeature->dereferenced, sizeof(anotherType_t)); } } } } 

产量

 found 'cursorFeature' at pos: 148, 378, 465, found 'penFeature' at pos: 1323, 

我的目标是以某种方式将这些结合起来,最好是组合成一个正则表达式(如果可能的话,我希望能够在VS内部进行搜索)。

这是使用Dot-Net正则表达式在VisualStudio IDE中执行此操作的方法。

不会产生误报。
我认为VS将跨​​越输出窗口中的行,这将使您能够
查看代码中的块,并在必要时查看数千个文件。

我已经在http://regexstorm.net/tester上测试了它,效果很好。
无法创建永久链接,它说它太长了..

但你可以在regexstorm自己尝试一下。

(如果你在C#程序集中使用它,你可以得到所有(多个) Vars
在捕获集合的循环中找到: CaptureCollection cc = Match.Groups["Vars"].Captures;
然后遍历cc。)

这是压缩的

Type.*<.*>\s*(\w+(?!\w))[^}]*?(?:while|for)\s*\(.*?(?:\r?\n)?.*?(?>\{(?>(?\1)(?!->|\+\+)|[^{}]|\{(?)|\}(?<-Depth>))*(?(Depth)(?!))(?(Vars)|(?!))\})

可读版本

  Type .* < .* > \s* ( # Type variable to find in Loop \w+ (?! \w ) # Must be an entire word ) [^}]*? (?: while | for ) # While or for loop \s* \( .*? (?: \r? \n )? .*? (?> \{ # Match opening { (?> # Then either match (possessively): (? \1 ) # Collect the Variable (?! -> | \+\+ ) # Not dereferencing or incrementing variable | # or [^{}] # Anything (but only if we're not at the start of { or } ) | # or \{ # { (and increase the braces counter) (? ) | # or \} # } (and decrease the braces counter). (?<-Depth> ) )* # Repeat as needed. (?(Depth) # Condition that the braces counter is at zero. (?!) # Fail if depth > 0 ) (?(Vars) # Condition that the Variables matched something | (?!) # Fail if Vars stack is empty ) \} # Then match a closing }. ) 

祝你好运,让我们知道结果如何!