我正试图想出办法来做到以下几点。给定一行文本(实际的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时我会遇到问题,但我还没有到达那里。对此问题的任何帮助将不胜感激。
如何将原线替换为三条线,我该怎么做?感谢。
答案 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
为空时的事情。