在文本文件中,我有一些变量声明,比如说:
long foo0,
foo1,
foo2 ;
long foo3;
short foo4;
short foo5, foo6 ;
long foo7, foo8 ;
我想使用Perl为所有“long”类型变量添加后缀“_r”,即。 foo0 / 1/2/3/7/8,预期输出为:
long foo0_r,
foo1_r,
foo2_r ;
long foo3_r;
short foo4;
short foo5, foo6 ;
long foo7_r, foo8_r ;
但是,我只能提出以下代码段:
#!/usr/bin/env perl
use strict;
use warnings;
while (<DATA>) {
#apply regex match and replace
s/(long\s+)(\w+)(\s*;)/$1$2_r$3/g;
#print current line.
print;
}
##inlined data filehandle for testing.
__DATA__
long foo0,
foo1,
foo2 ;
long foo3;
short foo4;
short foo5, foo6 ;
long foo7, foo8 ;
它只适用于foo3,但不适用于其他“长”的foos。诀窍是语法不是固定的;相反,“long”和“;”之间可能存在不确定数量的声明,由“,”分隔。任何人都可以提供一些关于代码的提示吗?
答案 0 :(得分:2)
我建议:
if (m/^long\b/) {
s/(\s\w+)/${1}_r/g;
}
更新问题的 修改:要支持多行声明,您可以先设置$/ = ';'
(这样&#34;行&#34;将由;
分隔比换行符...它有点像黑客,但这意味着while循环的每次迭代都会得到一个声明,而不是单个正常行)。然后,你需要在&#34; line&#34;开头的long
关键字之前支持空格。 (因为它将在上一个声明的分号后面有换行符),只需编写m/^\s*long\n/
而不是m/^long\n/
。最后,您需要支持而不是将long
转换为long_r
,这现在有点棘手。 (早些时候,我们依靠\s
的存在来区分它,但它不再起作用了。)最后一部分的一种方法是实际删除long
,然后打印它,之前进行添加_r
的替换。
总体:
$/ = ';';
while (<DATA>) {
if (s/(\s*long)\b//) {
print $1;
s/(\w+)/${1}_r/g;
}
print;
}
答案 1 :(得分:1)
编辑忘了处理逗号。现在已经解决了这个问题;
这是一种方法
while ( my $line = <DATA> ) {
# split line into type and vars
my ( $type, @vars ) = split(/[\s,;]+/, $line);
# if type is long, append '_r' to vars
if ( lc $type eq 'long' ) {
@vars = map { $_ . '_r' } @vars;
}
# join it all back together
print join(' ', $type, join(', ', @vars)) . ";\n";
}
__DATA__
long foo0, foo1, foo2 ;
long foo3;
short foo4;
short foo5, foo6 ;
<强>更新强>
更新了支持多行变量的解决方案...
my $state;
while ( my $line = <DATA> ) {
$state .= $line;
if ( $line =~ /;/ ) {
if ( $state =~ /long/ ) {
$state =~ s/(\s\w+)/$1_r/g;
}
print $state;
undef $state;
}
}
__DATA__
long foo0,
foo1,
foo2 ;
long foo3;
short foo4;
short foo5, foo6 ;
long foo7, foo8 ;
输出
long foo0_r,
foo1_r,
foo2_r ;
long foo3_r;
short foo4;
short foo5, foo6 ;
long foo7_r, foo8_r ;
答案 2 :(得分:1)
您可以使用(<dependency>...</dependency>)
更改记录分隔符,并使用否定lookbehind匹配该记录中不$/
的所有字词。
long
可生产
use strict;
use warnings;
$/=";";
while (<DATA>) {
s/(\w+\b)(?<!\blong)/$1_r/g if /^\s*long/;
print;
}
##inlined data filehandle for testing.
__DATA__
long foo0,
foo1,
foo2 ;
long foo3;
short foo4;
short foo5, foo6 ;
long foo7, foo8 ;
答案 3 :(得分:0)
我会用\ s逗号和分号分隔行,测试long是第一个单词,然后迭代其余的单词并追加_r并重新构造该行。