正则表达式以预先发现的模式替代(两步过程)

时间:2015-01-20 09:22:39

标签: regex perl

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

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

或者更好:

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

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

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

获得:

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

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

3 个答案:

答案 0 :(得分:1)

从命令行使用perl,

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

输出

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

答案 1 :(得分:1)

这可以通过\G anchor实现。锚\G匹配上一个匹配结束的位置。在第一次匹配尝试期间,\G\A的方式匹配字符串的开头。

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

DEMO

对于两者而言,单线就像,

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

答案 2 :(得分:0)

我建议您将@-@+数组与substr一起使用,以仅将翻译应用于所需部分。 (请参阅perlvar中的@LAST_MATCH_START@LAST_MATCH_END。)

喜欢这个

use strict;
use warnings;
use 5.010;

my $s = '#include "...\...\foo\bar.c" /* Here */// a \comment\ /\/';

say $s;

if ( $s =~ / \#include \s* ( "[^"]+" | <[^>]+> ) /x ) {
  substr($s, $-[1], $+[1]-$-[1]) =~ tr|\\|/|;
}

say $s;

<强>输出

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