扩展 Mark Moretto 的出色回答:
在 Visual Studio 2019 中,这在我的整个 C++ 代码库中运行良好:
替换这个:
(.*print[(])(".*?")(.*[)];)
有了这个:
$1FMT_STRING($2)$3
然后重复这个来处理fmt::format
:
(.*format[(])(".*?")(.*[)];)
对于全局 Search'n'Replace,确保打开的RegEx
图标.*
。
我使用.NET Regex Tester来形成表达式。
它在大约 5 秒内正确修复了 505 个实例中的 500 个,但它确实因我手动修复的这种事情而绊倒:
// Required manual fix (shift rogue bracket away from end).
auto y = format("Test=\"{}\""), 42);
说明(可选)
我一直发现 RegEx 表达式非常复杂,但是通过这个示例的工作不知何故在我的脑海中打开了一个灯泡开关。
(.*print[(])
匹配从行首到开头的任何内容print(
并替换为$1
.
(".*?")
匹配从开头到结尾的引号,并替换为$2
.
(.*[)];)
将所有内容与结尾匹配);
,并替换为$3
.
$1FMT_STRING($2)$3
插入FMT_STRING()
正确的位置。
笔记:
- 关于第 1 点:
- 注意使用
[(]
来表示文字(
。
- 注意使用
.*
. 这是一个通配符,.
表示任何字符并*
表示任何重复次数。
- 它也将匹配在
fmt::print(
. 需要不同的正则表达式来处理format(
和fmt::format(
(见上文)。
- 关于第 2 点:
- 注意使用
?
来表示它应该在它看到的第一个结束引号处停止(即“非贪婪匹配”)。
附录 A:测试用例(可选)
将以下内容粘贴Input Tests Cases
到.NET Regex Tester中,以突出显示语法并更轻松地编辑表达式以稍微修改它。
输入测试用例:
// Test non-namespace match.
print("Hello, world!");
print("Test: {}", 42);
print("Test: {}: {}", 42, "A");
print("Test: {:0}: {} : {}", 42, "A", myVariable);
print("{}, {}, {}", 42, "A", "B");
print("Hello, world!");
print("Test: {}", 42);
print("Test: {}: {}", 42, "A");
print("Test: {:0}: {} : {}", 42, "A", myVariable);
print("{}, {}, {}", 42, "A", "B");
// Test namespace match.
fmt::print("Hello, world!");
fmt::print("Test: {}", 42);
fmt::print("Test: {}: {}", 42, "A");
fmt::print("Test: {:0}: {} : {}", 42, "A", myVariable);
fmt::print("{}, {}, {}", 42, "A", "B");
fmt::print("Hello, world!");
fmt::print("Test: {}", 42);
fmt::print("Test: {}: {}", 42, "A");
fmt::print("Test: {:0}: {} : {}", 42, "A", myVariable);
fmt::print("{}, {}, {}", 42, "A", "B");
// Test compatibility with existing (should be no change).
fmt::print(FMT_STRING("Hello, world!"));
fmt::print(FMT_STRING("Test: {}"), 42);
fmt::print(FMT_STRING("Test: {}: {}"), 42, "A");
fmt::print(FMT_STRING("Test: {:0}: {} : {}"), 42, "A", myVariable);
fmt::print(FMT_STRING("{}, {}, {}"), 42, "A", "B");
fmt::print("Hello, world!");
fmt::print(FMT_STRING("Test: {}"), 42);
fmt::print(FMT_STRING("Test: {}: {}"), 42, "A");
fmt::print(FMT_STRING("Test: {:0}: {} : {}"), 42, "A", myVariable);
fmt::print(FMT_STRING("{}, {}, {}"), 42, "A", "B");
测试用例的输出(全部正确):
// Test non-namespace match.
print(FMT_STRING("Hello, world!"));
print(FMT_STRING("Test: {}"), 42);
print(FMT_STRING("Test: {}: {}"), 42, "A");
print(FMT_STRING("Test: {:0}: {} : {}"), 42, "A", myVariable);
print(FMT_STRING("{}, {}, {}"), 42, "A", "B");
print(FMT_STRING("Hello, world!"));
print(FMT_STRING("Test: {}"), 42);
print(FMT_STRING("Test: {}: {}"), 42, "A");
print(FMT_STRING("Test: {:0}: {} : {}"), 42, "A", myVariable);
print(FMT_STRING("{}, {}, {}"), 42, "A", "B");
// Test namespace match.
fmt::print(FMT_STRING("Hello, world!"));
fmt::print(FMT_STRING("Test: {}"), 42);
fmt::print(FMT_STRING("Test: {}: {}"), 42, "A");
fmt::print(FMT_STRING("Test: {:0}: {} : {}"), 42, "A", myVariable);
fmt::print(FMT_STRING("{}, {}, {}"), 42, "A", "B");
fmt::print(FMT_STRING("Hello, world!"));
fmt::print(FMT_STRING("Test: {}"), 42);
fmt::print(FMT_STRING("Test: {}: {}"), 42, "A");
fmt::print(FMT_STRING("Test: {:0}: {} : {}"), 42, "A", myVariable);
fmt::print(FMT_STRING("{}, {}, {}"), 42, "A", "B");
// Test compatibility with existing (should be no change).
fmt::print(FMT_STRING("Hello, world!"));
fmt::print(FMT_STRING("Test: {}"), 42);
fmt::print(FMT_STRING("Test: {}: {}"), 42, "A");
fmt::print(FMT_STRING("Test: {:0}: {} : {}"), 42, "A", myVariable);
fmt::print(FMT_STRING("{}, {}, {}"), 42, "A", "B");
fmt::print(FMT_STRING("Hello, world!"));
fmt::print(FMT_STRING("Test: {}"), 42);
fmt::print(FMT_STRING("Test: {}: {}"), 42, "A");
fmt::print(FMT_STRING("Test: {:0}: {} : {}"), 42, "A", myVariable);
fmt::print(FMT_STRING("{}, {}, {}"), 42, "A", "B");