在匹配时使用正则表达式进行搜索,替换和重复?

时间:2015-07-27 21:56:41

标签: regex perl

我正试图想出办法来做到以下几点。给定一行文本(实际的Fortran77代码,这些声明从第7列开始)

  CHARACTER FOO*1, BAR*2, OTHER*6

将其替换为

  CHARACTER*1 FOO
  CHARACTER*2 BAR
  CHARACTER*6 OTHER

我试过这个

perl -pe '1 while s/^[^*][ ]+CHARACTER[ ]+([a-z-A-Z0-9_]+)\*([0-9]+)(,?)(.*)/      CHARACTER\*$2 $1\n      CHARACTER $4/' foo.f

[^ *]位是故意的(我在第1列忽略带*的行)。我得到的输出是

  CHARACTER*1 FOO
  CHARACTER BAR*2, OTHER*6

我已经看到,只剩下CHARACTER OTHER * 6时我会遇到问题,但我还没有到达那里。对此问题的任何帮助将不胜感激。

如何将原线替换为三条线,我该怎么做?感谢。

3 个答案:

答案 0 :(得分:4)

perl -ple 'if (/^( +CHARACTER) +(\w+\*\d+(?:, *\w+\*\d+)*) *$/) { my $p = $1; $_ = join "\n", map /(\w+)\*(\d+)/ ? "$p*$2 $1" : die("wtf: $_"), split /,/, $2; }' foo.f

男人,这在一行看起来很糟糕。格式化:

perl -ple '
if (/^( +CHARACTER) +(\w+\*\d+(?:, *\w+\*\d+)*) *$/) {
    my $p = $1;
    $_ = 
        join "\n",
        map /(\w+)\*(\d+)/ ? "$p*$2 $1" : die("wtf: $_"),
        split /,/,
        $2;
    }
' foo.f

答案 1 :(得分:0)

我想到的第一件事是:

# Open file containing the line and loop through lines (I put only one line)
open (INFH, '<', "num.txt");

while(<INFH>){
    @arr = split(',',$_);
    foreach $arrEle (@arr){
        if ($arrEle =~ /CHARACTER/){
            $arrEle =~ s/(\s+)(\w+)(\s+)(\w+)(\*)(\d+)/$1$2$5$6$3$4/;
        }else{
            $arrEle =~ s/(\s+)(\w+)(\*)(\d+)/\tCHARACTER$3$4$1$2/;
        }
        print "$arrEle\n";
    }
}

我将在评论部分讨论更新详情。

这应该适用于任何大的行,例如:

CHARACTER FOO*1, BAR*2, OTHER*6, OTHERS*7, OTHERS*8依此类推

答案 2 :(得分:0)

您的原始尝试只缺少一件事:^默认情况下仅匹配字符串的开头,但您希望匹配字符串中间一行的开头。将您的s/.../.../更改为s/.../.../m

然后你仍然需要处理最后的替换;要么使,必须匹配,要添加第二个替换来处理最终*length的移动或使用/e并使得替换为不同的表达式$3为空时的事情。