查找模式,但不在 C++ 注释中
Find a pattern, but not within a C++ comment
我有一个正则表达式,可以在大型代码库中搜索用作类型或变量的特定标记的用法。假设令牌是 "foo",我想将其作为作品单独查找。
我的初始正则表达式是这样的:
foo$|foo\s|foo\[|foo\*|<foo|foo>
匹配:行尾的 foo、带 space 的 foo、指针 foo、集合中的 foo 等...
我想排除 C++ 评论框中的实例。比如下面这个例子。
// consume the foo and read another.
我试过使用负前瞻修改正则表达式,但这似乎不起作用
(?!\/\/).*(foo$|foo\s|foo\[|foo\*|<foo|foo>)
有人知道如何在正则表达式中执行此操作吗?
更新:
我只是想随便过滤掉目标模式之前可能有两个正斜杠的行。我不关心嵌套注释、C 风格注释 (/* */) 或任何跨越多行的内容。
正则表达式不是最好的工具。
我写了一个 C 到 Delphi 的转换器 (https://github.com/WouterVanNifterick/C-To-Delphi),我确实在其中使用正则表达式来完成某些任务,但我的结论是正则表达式不是你想做什么。
我可以说,因为我已经尝试过,并决定放弃正则表达式,因为事情变得过于复杂而且无法可靠地工作。
您可以快速创建适用于 90% 情况的内容,但如果您想正确处理嵌套注释或看起来像注释的字符串,解析是唯一的选择。
你不需要完整的 C++ 解析器。您需要遍历所有字符,并跟踪您是否在 /* */ 块、"" 字符串块或 // 部分中,然后执行您需要执行的操作。
这是一个相当全面的正则表达式,可以满足您的要求(在 Perl 中测试):
my $foo_regex = qr{
\G
(?>
# // comment
/ (?: \ \n )*+ / (?> \ \n | [^\n] )*+
|
# /* comment */
/ (?: \ \n )*+ \* (?> .*? \* (?: \ \n )*+ / )
|
# 'c'
' (?: [^'\\n] | \ . )++ '
|
# "string"
" (?: [^"\\n] | \ . )*+ "
|
# R"(raw string)"
\b
(?: (?> [LU] | u (?: \ \n )*+ 8?+ ) (?: \ \n )*+ )?+
R
(?: \ \n )*+
"
(?: \ \n )*+
( [^()\\s]?+ )
(?: \ \n )*+
( [^()\\s]?+ )
(?: \ \n )*+
( [^()\\s]?+ )
(?: \ \n )*+
( [^()\\s]?+ )
(?: \ \n )*+
( [^()\\s]?+ )
(?: \ \n )*+
( [^()\\s]?+ )
(?: \ \n )*+
( [^()\\s]?+ )
(?: \ \n )*+
( [^()\\s]?+ )
(?: \ \n )*+
( [^()\\s]?+ )
(?: \ \n )*+
( [^()\\s]?+ )
(?: \ \n )*+
( [^()\\s]?+ )
(?: \ \n )*+
( [^()\\s]?+ )
(?: \ \n )*+
( [^()\\s]?+ )
(?: \ \n )*+
( [^()\\s]?+ )
(?: \ \n )*+
( [^()\\s]?+ )
(?: \ \n )*+
( [^()\\s]?+ )
(?: \ \n )*+
\(
(?>
.*?
\)
(?: \ \n )*+
\g{-16}
(?: \ \n )*+
\g{-15}
(?: \ \n )*+
\g{-14}
(?: \ \n )*+
\g{-13}
(?: \ \n )*+
\g{-12}
(?: \ \n )*+
\g{-11}
(?: \ \n )*+
\g{-10}
(?: \ \n )*+
\g{-9}
(?: \ \n )*+
\g{-8}
(?: \ \n )*+
\g{-7}
(?: \ \n )*+
\g{-6}
(?: \ \n )*+
\g{-5}
(?: \ \n )*+
\g{-4}
(?: \ \n )*+
\g{-3}
(?: \ \n )*+
\g{-2}
(?: \ \n )*+
\g{-1}
(?: \ \n )*+
"
)
|
# / (not starting a comment)
/ (?! (?: \ \n )*+ [/*] )
|
# identifier
\w (?: (?: \ \n )*+ \w )*+
|
# arbitrary other character
[^/"'\w]
)*?
\b
(
f
(?: \ \n )*+
o
(?: \ \n )*+
o
)
(?!
(?: \ \n )*+
\w
)
}xms;
它所考虑的并发症概述:
"foo"
、'foo'
、// foo
、/* foo */
不是foo
的出现,而是字符串文字、多字符常量、单-分别是行注释和块注释。
/* " */
、// "
、" /* "
、'//'
等分别是注释、注释、字符串字面量、多字符常量。这意味着您不能分阶段过滤掉字符串文字、注释等;您必须一次全部解析它们,以避免将引用结构的内容误认为是另一个引用结构的定界符。
必须忽略反斜杠换行符组合(就好像它们不存在于源文件中一样):
/\
* this is a comment */
/\
/ and so is this
foo\
bar // this is a single identifier, 'foobar'
f\
oo // ... but this is 'foo'
"this is a string\
" <- that's not the end of the string; this is: "
- 这个正则表达式的很大一部分处理
R"delim(...)delim"
形式的原始字符串文字,并结合可以散布在任何地方的任意反斜杠换行符对。幸运的是,C++ 指定了最多 16 个自定义分隔符的上限;否则我们将不得不使用运行时代码执行/动态正则表达式生成。
- 不处理三字母。如果要添加支持,请首先将正则表达式中每次出现的
\
更改为 (?> \ | \?\?/ )
.
更新:为了您的简化要求(在字符串中找到 foo
前面没有 //
的单词),您可以简单地执行 ^(?:[^/]|/(?!/))*?\bfoo\b
.
我有一个正则表达式,可以在大型代码库中搜索用作类型或变量的特定标记的用法。假设令牌是 "foo",我想将其作为作品单独查找。
我的初始正则表达式是这样的:
foo$|foo\s|foo\[|foo\*|<foo|foo>
匹配:行尾的 foo、带 space 的 foo、指针 foo、集合中的 foo 等...
我想排除 C++ 评论框中的实例。比如下面这个例子。
// consume the foo and read another.
我试过使用负前瞻修改正则表达式,但这似乎不起作用
(?!\/\/).*(foo$|foo\s|foo\[|foo\*|<foo|foo>)
有人知道如何在正则表达式中执行此操作吗?
更新:
我只是想随便过滤掉目标模式之前可能有两个正斜杠的行。我不关心嵌套注释、C 风格注释 (/* */) 或任何跨越多行的内容。
正则表达式不是最好的工具。
我写了一个 C 到 Delphi 的转换器 (https://github.com/WouterVanNifterick/C-To-Delphi),我确实在其中使用正则表达式来完成某些任务,但我的结论是正则表达式不是你想做什么。 我可以说,因为我已经尝试过,并决定放弃正则表达式,因为事情变得过于复杂而且无法可靠地工作。
您可以快速创建适用于 90% 情况的内容,但如果您想正确处理嵌套注释或看起来像注释的字符串,解析是唯一的选择。
你不需要完整的 C++ 解析器。您需要遍历所有字符,并跟踪您是否在 /* */ 块、"" 字符串块或 // 部分中,然后执行您需要执行的操作。
这是一个相当全面的正则表达式,可以满足您的要求(在 Perl 中测试):
my $foo_regex = qr{
\G
(?>
# // comment
/ (?: \ \n )*+ / (?> \ \n | [^\n] )*+
|
# /* comment */
/ (?: \ \n )*+ \* (?> .*? \* (?: \ \n )*+ / )
|
# 'c'
' (?: [^'\\n] | \ . )++ '
|
# "string"
" (?: [^"\\n] | \ . )*+ "
|
# R"(raw string)"
\b
(?: (?> [LU] | u (?: \ \n )*+ 8?+ ) (?: \ \n )*+ )?+
R
(?: \ \n )*+
"
(?: \ \n )*+
( [^()\\s]?+ )
(?: \ \n )*+
( [^()\\s]?+ )
(?: \ \n )*+
( [^()\\s]?+ )
(?: \ \n )*+
( [^()\\s]?+ )
(?: \ \n )*+
( [^()\\s]?+ )
(?: \ \n )*+
( [^()\\s]?+ )
(?: \ \n )*+
( [^()\\s]?+ )
(?: \ \n )*+
( [^()\\s]?+ )
(?: \ \n )*+
( [^()\\s]?+ )
(?: \ \n )*+
( [^()\\s]?+ )
(?: \ \n )*+
( [^()\\s]?+ )
(?: \ \n )*+
( [^()\\s]?+ )
(?: \ \n )*+
( [^()\\s]?+ )
(?: \ \n )*+
( [^()\\s]?+ )
(?: \ \n )*+
( [^()\\s]?+ )
(?: \ \n )*+
( [^()\\s]?+ )
(?: \ \n )*+
\(
(?>
.*?
\)
(?: \ \n )*+
\g{-16}
(?: \ \n )*+
\g{-15}
(?: \ \n )*+
\g{-14}
(?: \ \n )*+
\g{-13}
(?: \ \n )*+
\g{-12}
(?: \ \n )*+
\g{-11}
(?: \ \n )*+
\g{-10}
(?: \ \n )*+
\g{-9}
(?: \ \n )*+
\g{-8}
(?: \ \n )*+
\g{-7}
(?: \ \n )*+
\g{-6}
(?: \ \n )*+
\g{-5}
(?: \ \n )*+
\g{-4}
(?: \ \n )*+
\g{-3}
(?: \ \n )*+
\g{-2}
(?: \ \n )*+
\g{-1}
(?: \ \n )*+
"
)
|
# / (not starting a comment)
/ (?! (?: \ \n )*+ [/*] )
|
# identifier
\w (?: (?: \ \n )*+ \w )*+
|
# arbitrary other character
[^/"'\w]
)*?
\b
(
f
(?: \ \n )*+
o
(?: \ \n )*+
o
)
(?!
(?: \ \n )*+
\w
)
}xms;
它所考虑的并发症概述:
"foo"
、'foo'
、// foo
、/* foo */
不是foo
的出现,而是字符串文字、多字符常量、单-分别是行注释和块注释。/* " */
、// "
、" /* "
、'//'
等分别是注释、注释、字符串字面量、多字符常量。这意味着您不能分阶段过滤掉字符串文字、注释等;您必须一次全部解析它们,以避免将引用结构的内容误认为是另一个引用结构的定界符。必须忽略反斜杠换行符组合(就好像它们不存在于源文件中一样):
/\ * this is a comment */ /\ / and so is this foo\ bar // this is a single identifier, 'foobar' f\ oo // ... but this is 'foo' "this is a string\ " <- that's not the end of the string; this is: "
- 这个正则表达式的很大一部分处理
R"delim(...)delim"
形式的原始字符串文字,并结合可以散布在任何地方的任意反斜杠换行符对。幸运的是,C++ 指定了最多 16 个自定义分隔符的上限;否则我们将不得不使用运行时代码执行/动态正则表达式生成。 - 不处理三字母。如果要添加支持,请首先将正则表达式中每次出现的
\
更改为(?> \ | \?\?/ )
.
更新:为了您的简化要求(在字符串中找到 foo
前面没有 //
的单词),您可以简单地执行 ^(?:[^/]|/(?!/))*?\bfoo\b
.