鉴于以下(已消毒)输入:
Return_t
func()
{
Type<SubType> cursorFeature(true);
while (nDist < 800)
{
Result = Example(&var, 0, cursorFeature); //interested in this because inside loop, and not dereferenced or incremented
if (!(++cursorFeature).NoMoreRecords())
{
if (!BLAH(blah)
&& (otherFunc(&var, &cursorFeature->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(?<!\+\+)\1(?!->|\+\+)
https://regex101.com/r/Kr0zQq/4
我的目标是以某种方式将这些组合在一起,最好是 ONE 正则表达式(如果可能的话,我希望能够在VS内部进行搜索)。鉴于递归正则表达式的性质,我不确定这是不可能的......我怀疑它不是。如果没有,那么在搜索数百个文件时不会丢失文件名/数字上下文的聪明的东西会很棒。我基本上需要文件名和行号。上下文很棒,但不是必需的。
为了澄清,我想捕获cursorFeature
,因为它的类型为Type
,然后我想在"loop"{.....}
编辑
关于我使用正则表达式解决此问题的说明。被搜索的代码超过一百万行,跨越由各种编译器编译并由多个构建系统构建的多个项目。例如,使用宏和高级语言功能意味着甚至VS Intellisense 经常错误地编写VS能够编译的代码。和YCM(vim)一样。因此,一个可能过于贪婪的正则表达式,即70%的误报是好的。 (由于缺少循环中变量使用的进一步发生,因为在那一点上通常很容易扫描其余部分。)然而,尝试使用“通用”PCRE作为单行程执行此操作可能是愚蠢的。 :)
答案 0 :(得分:5)
您可以通过三个选项查看以下循环中是否存在匹配的变量名称。第一个是将(\1)
添加到原子组并检查您的环境中是否存在此捕获组(如果可能的话):
(?>(\1)|[^{}]|(?-2))*
其次,你可以通过使用负向前瞻来缓和[^{}]
的匹配过程:
(?>(?!\1)[^{}]|(?-1))*
但是如果你没有像我在评论中提供的演示中所做的那样选择右括号,它就会失败。
第三个更好的解决方法是使用动词(*ACCEPT)
,这会立即导致成功匹配的结束,而不会在正则表达式中进行进一步更改:
(?>(\1)(*ACCEPT)|[^{}]|(?-2))*
答案 1 :(得分:1)
使用单个正则表达式执行此操作需要使用Perl代码块
和有条件的代码。
虽然接受的答案很好,但它无法验证Type变量
将存在于平衡循环内。
这里的代码只是存储Type变量的位置 在所有嵌套循环中找到。它不会错过任何一个。
作为一个例子,我在一些文件中为多个位置播种了数据集 循环,其他地方的单一位置,另一个没有。
除了字符串中的位置之外,你如何定位取决于你。
Perl
use strict;
use warnings;
$/ = undef;
my $data = <DATA>;
my @vals;
while ( $data =~ /
(?{ @vals = () }) # Code block - Initialize @vals
Type .* < .* > \s*
( \w+ ) # (1)
[^}]*?
(?: while | for )
\s* \( .*?
(?: \r? \n )?
.*?
(?<core> # (2 start)
\{
(?>
(?<! \+\+ )
( \1 ) # (3)
(?! -> | \+\+ )
(?{
# 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<SubType> 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<SubType> 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<SubType> 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,
答案 2 :(得分:1)
我的目标是以某种方式将这些结合起来,最好是合并到一个正则表达式中(如果可能的话,我希望能够在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)?.*?(?>\{(?>(?<!\+\+)(?<Vars>\1)(?!->|\+\+)|[^{}]|\{(?<Depth>)|\}(?<-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):
(?<! \+\+ ) # Not incrementing variable
(?<Vars> \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)
(?<Depth> )
| # 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 }.
)
祝你好运,让我们知道结果如何!