输入数据(示例):
40A3B35A3C
30A5B28A2C2B
所需输出(每行)是由代码40A3B35A3C的组成和以下规则确定的单个数字:
if A - add the proceeding number to the running total
if B - add the proceeding number to the running total
if C - subtract the proceeding number from the running total
40A 3B 35A 3C
因此会产生40 + 3 + 35 - 3 = 75。
两行的输出:
75
63
是否有一种有效的方法可以使用单行程序在制表符分隔的.txt文件中为特定列(例如$F[2]
)实现此目的?我考虑将整个代码分成单个字符,然后执行if语句检查以检测A / B / C,但我的Perl知识有限,我不确定如何解决这个问题。
答案 0 :(得分:3)
当您使用split
捕获时,捕获的组也会从拆分返回。
perl -lane '
@ar = split /([ABC])/, $F[2];
$s = 0;
$s += $n * ("C" eq $op ? -1 : 1) while ($n, $op) = splice @ar, 0, 2;
print $s
' < input
或许更具说明性:
BEGIN { %one = ( A => 1,
B => 1,
C => -1 ) }
@ar = split /([ABC])/, $F[2];
$s = 0;
$s += $n * $one{$op} while ($n, $op) = splice @ar, 0, 2;
print $s
答案 1 :(得分:1)
当处理像这样的字符串时,知道正则表达式可以返回结果列表是有用的。
E.g。
my @matches = $str =~ m/(\d+[A-C])/g; #will catch repeated instances
所以你可以这样做:
#!/usr/bin/env perl
use strict;
use warnings;
while (<DATA>) {
my $total;
#break the string into digit+letter groups.
for (m/(\d+[A-C])/g) {
#separate out this group into num and code.
my ( $num, $code ) = m/(\d+)([A-C])/;
print "\t",$num, " => ", $code, "\n";
if ( $code eq "C" ) {
$total -= $num;
}
else {
$total += $num;
}
}
print $total, " => ", $_;
}
__DATA__
40A3B35A3C
30A5B28A2C2B
答案 2 :(得分:1)
perl -lne 'push @a,/([\d]+)[AB]/g;
push @b,/([\d]+)[C]/g;
$sum+=$_ for(@a);$sum-=$_ for(@b);
print $sum;@a=@b=();undef $sum' Your_file
答案 3 :(得分:1)
如何运作
use strict;
use warnings;
my %op=qw(A + B + C -);
$ARGV[0] =~ s/(\d+)(A|B|C)/$op{$2} $1/g;
print eval($ARGV[0]);