正则表达式在预先找到的模式中替换(两步过程)



我想用/替换#include <...>指令中的所有。我想一次性完成。不幸的是,我只发现这需要几行:

if(/^s*#includes*(?:"|<)K.*\.*(?="|>)/) {
   my $r = $& =~ s|\|/|gr;
   s/Q$&E/$r/g;
}

或者也许更好:

if(/^(s*#includes*(?:"|<))(.*\.*)((?:"|>).*)$/) {
   my $r = $2 =~ s|\|/|gr;
   s/Q$1$2$3E/$1$r$3/g;
}

例如,我可以有这样的输入:

    #include "......foobar.c" /* Here */// a comment //

并获得:

    #include ".../.../foo/bar.c" /* Here */// a comment //

我可以让它更好、更漂亮、更短吗?

可以通过G锚点来实现。锚点G在上一个匹配结束的位置匹配。在第一次匹配尝试期间,GA方式在字符串开头进行匹配。

$ echo '    #include "......foobar.c" /* Here */// a comment //' | perl -pe 's~(?:^s*#includes*"|G)[^\"]*K\~/~g'
    #include ".../.../foo/bar.c" /* Here */// a comment //
$ echo '    #include "......foobar.c" /* Here */// a comment //' | perl -pe 's~(?:^s*#includes*"|G)[^\"]*K\(?=[^"]*")~/~g'
    #include ".../.../foo/bar.c" /* Here */// a comment //

演示

对于两者,单行代码就像,

$ echo '#include "......foobar.c" /* Here */// a comment // "foobar"
  #include <......foobar.c> foo\bar' | perl -pe 's~(?:(?:^s*#includes*"|G)[^\">]*K\)|(?:(?:^s*#includes*<|G)[^\><]*K\(?=[^<>]*>))~/~g'
#include ".../.../foo/bar.c" /* Here */// a comment // "foobar"
  #include <.../.../foo/bar.c> foo\bar

从命令行使用 perl,

perl -i pe 's{^s*#includes*[<"]+K ([^">]+) (?=[">]+)}{ $1 =~ y|\|/|r }xe' file

输出

#include ".../.../foo/bar.c" /* Here */// a comment //

我建议你使用带有substr@-@+数组,以仅将转换应用于所需的部分。 (请参阅perlvar中的@LAST_MATCH_START@LAST_MATCH_END

喜欢这个

use strict;
use warnings;
use 5.010;
my $s = '#include "......foobar.c" /* Here */// a comment //';
say $s;
if ( $s =~ / #include s* ( "[^"]+" | <[^>]+> ) /x ) {
  substr($s, $-[1], $+[1]-$-[1]) =~ tr|\|/|;
}
say $s;

输出

#include "......foobar.c" /* Here */// a comment //
#include ".../.../foo/bar.c" /* Here */// a comment //

最新更新