给定以下(净化)输入:
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*)[sS]*?K(?<!++)1(?!->|++)
https://regex101.com/r/Kr0zQq/4
我的目标是以某种方式将这些组合在一起,最好是合并到一个正则表达式中(如果可能的话,我也希望能够从 VS 中进行此搜索)。 鉴于递归正则表达式的性质,我不确定这是否可能......我怀疑不是。 如果没有,在搜索数百个文件时不会丢失文件名/编号上下文的聪明东西会很棒。 我基本上需要文件名和行号。 上下文很好,但不是必需的。
澄清一下,我想捕获cursorFeature
因为它的类型是Type
,然后我想在"loop"{.....}
中搜索它的使用
编辑
只是关于我使用正则表达式来解决这个问题的说明。 正在搜索的代码超过一百万行,跨越由各种编译器编译并由多个构建系统构建的多个项目。 例如,同时使用宏和高级语言功能意味着,即使是 VS Intellisense 也经常错误地解析 VS 能够编译的代码。 YCM(vim)也是如此。 因此,一个可能过于贪婪的正则表达式是 70% 误报是可以的。 (因为缺少循环中变量使用的进一步出现,因为此时通常很容易扫描其余部分。 然而,试图使用"通用"PCRE作为单行代码来做到这一点可能是愚蠢的。:)
您有三个选项来查看以下循环中是否存在匹配的变量名称。第一个是将(1)
添加到原子组,并检查环境中是否存在此捕获组(如果可能):
(?>(1)|[^{}]|(?-2))*
其次,您可以通过使用负面的前瞻来缓和[^{}]
的匹配过程:
(?>(?!1)[^{}]|(?-1))*
但是如果您不像我在评论中提供的演示中所做的那样使右大括号可选,它将失败。
第三个也是更好的解决方法是使用动词(*ACCEPT)
,它会导致成功匹配立即结束,而无需对正则表达式进行进一步更改:
(?>(1)(*ACCEPT)|[^{}]|(?-2))*
现场演示
要使用单个正则表达式执行此操作,需要使用 Perl 代码块
和代码条件。
虽然接受的答案很好,但它无法验证 Type 变量
是否存在于平衡循环中。
这里的代码只存储 Type 变量的位置,因为它在所有
嵌套循环中找到。它不会错过任何一个。
例如,我在某些
循环中为数据集设定了多个位置的种子,在其他循环中具有单个位置,而在另一个循环中没有位置。
除了字符串中的位置之外,您如何定位取决于您。
佩尔
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,
我的目标是以某种方式将这些组合在一起,最好是合并到一个正则表达式中(如果可能的话,我也希望能够在 VS 中进行此搜索)。
这是在VisualStudio IDE中使用Dot-Net正则表达式执行此操作的一种方法。
这不会产生误报。
我认为VS将在输出窗口中跨越行,这将使您能够
查看代码中的块,并在必要时跨数千个文件。
我已经在 http://regexstorm.net/tester 对此进行了测试,效果很好。
无法创建永久链接,它说它太长了。
但是您可以在正则表达式风暴中自己尝试。
(如果要在 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 }.
)
祝你好运,让我们知道结果如何!