提问人:Ichwerdennauchsonst 提问时间:8/4/2023 最后编辑:Ichwerdennauchsonst 更新时间:8/29/2023 访问量:88
Sed regexp 仅匹配无效的 c++ 标识符字符以重命名变量
Sed regexp Match only non-valid c++ identifier characters to rename a variable
问:
我想使用 sed 重命名变量名称(标识符)。我想为 c++ 做这件事,但是对于其他语言来说,情况会类似。假设我们有一个这样的代码示例: 示例.cpp
int hi;
int bye;
...//a lot of code with many occurences of n
假设出于任何原因,我想在 hello 中重命名 hi。问题是 hi 可以作为其他词的一部分出现。在 C++ 中,有效的标识符具有以下收据:(将扩展字符放在一边,例如或放在一边。我不知道 alnum 是否包含这些,但如果它们没有问题,也许可以期待扩展的标点符号字符,但谁使用它们)[[[:alpha:]]_]+[[[:alnum:]]_]
ä
龍
有效标识符旁边必须有一个与此表达式无关的字符,以将其与其他标识符区分开来。因此,不允许在之前和之后使用,而任何其他字符都可以。另一个问题是字符串。这只有在字符串始终在内联时才有效。然后我们必须检查 unescpaped 的奇数出现“,如果我们可以使用正则表达式做到这一点,这可能是一个数学问题,但是我没有达到这一点,第一次在没有字符串识别的情况下尝试:n
[[[:alnum:]]_]
""
sed -i -e 'hi/\([^[[:alnum:]]_]\)hello\([^[[:alnum:]]_]\)/\1r\2/g' example.cpp
它没有改变任何东西
答:
你的 sed 是乱码 -- 没有替代品。s///
无论如何,您所需要的只是在替换的匹配端中使用单词边界 ():\b
sed 's/\bhi\b/hello/' example.cpp
上面的作用与此几乎相同:
sed -E 's/([^[:alnum:]_])hi([^[:alnum:]_])/\1hello\2/' example.cpp
...除了上述取决于匹配组的大小为非零。
另请注意,字符类的方括号多于所需数。的否定是,所以你的非单词字符类应该是 。这相当于在扩展正则表达式 (ERE) 中,因此您也可以使用:[[:alnum:]]
[^[:alnum:]]
[^[:alnum:]_]
\W
sed -E
sed -E 's/(\W)hi(\W)/\1hello\2/' example.cpp
...再次需要注意的是,在之前或之后必须有一个非单词字符(这可能是 C 变量的安全假设)。hi
要解决此问题,您也可以将行开头和结尾大小写添加到此行,这允许在这些情况下进行零大小匹配:^
$
sed -E 's/(^|\W)hi(\W|$)/\1hello\2/' example.cpp
(上面可能工作得很好,与sed 's/\bhi\b/hello/'
)
或者你可以使用 perl 正则表达式 (PCRE) 来使匹配组具有非消耗性 lookbehind 和 lookahead:(?<=)
(?=)
perl -pe 's/(?<=\W)hi(?=\W)/hello/' example.cpp
与此相同,反转 char 组并否定 lookbehind 和 lookahead:
perl -pe 's/(?<!\w)hi(?!\w)/hello/' example.cpp
随着 GNU 正则表达式功能集的扩展,你可以用 grep 测试所有功能的匹配:
$ grep --color '\bhi\b' example.cpp
$ grep -E --color '(^|\W)hi(\W|$)' example.cpp
$ grep -P --color '(?<!\w)hi(?!\w)' example.cpp
...因此,您将看到使用基本、扩展 (ERE) 和 perl (PCRE) 正则表达式以颜色突出显示,所有这些都受 grep 支持。(上面的 ERE 还突出显示了之前或之后的非单词字符(如果有))hi
但是,所有正则表达式样式都支持始终方便的单词边界零大小匹配。所以,使用它。\b
评论
sed
n
r
)sed