Perl,从文本文件第 2 列中的每个值中减去 8

Perl, Minus 8 from every value in column 2 in a text file

这适用于第一列。我怎么能把它改成只在第二个工作?我仍然可以在一行中完成它还是必须将其扩展为一个 .pl 文件?

列之间用逗号分隔 space ", "

perl -pe 's/^([-0-9]+)/ - 8/e' your_file > output.txt

详情:

文件示例。

Title1, Title2, Title3, ..., Titlen

12456, 45, 21, 686731, ...

21, 6876546, 987, 134561, ...

当 perl 大师们正在思考答案时,这里是 awk 解决方案:

> echo '5 10 15\n20 25 30' | awk '{-=8; print}'
5 2 15
20 17 30

更新

假设您有一个文件 x.txt,其格式与您的示例文件相同:

> cat x.txt
t1, t2, t3
1, 12, 3
-4, 22, 13

使用此命令,您可以从第二列的每个数字字段中减去 8:

> awk -F, 'BEGIN {OFS=","} {if (+0==) {-=8}; print}' x.txt > output.txt

> cat output.txt
t1, t2, t3
1,4, 3
-4,14, 13

这里 -F,BEGIN {OFS=","} 告诉 awk 使用逗号作为 input/output 字段分隔符。大括号中的下一个块将针对每个输入行进行评估。因此,对于每个输入行,我们测试第二个字段是否为数字 (+0==),如果是,则从中减去 8,并打印结果行。输入文件为x.txt,输出将从标准输出重定向到文件output.txt.

在此示例中,字符串被标记化为一个数组。正则表达式版本会更短一些(就像 awk)。 它还会跳过非字符串上的 -8。

perl -ne '@a = split /,\s+/, $_; if($a[1] =~ /^\d*$/) {$a[1] = $a[1] - 8}; print join ", ", @a;'  foo


cat foo 
Title1, Title2, Title3
12456, 45, 21, 68673
21, 6876546, 987, 134561

perl -ne '@a = split /,\s+/, $_; if($a[1] =~ /^\d*$/) {$a[1] = $a[1] - 8}; print join ", ", @a;'  foo
Title1, Title2, Title3
12456, 37, 21, 68673
21, 6876538, 987, 134561

在您的文件示例中,字段以逗号和空格分隔。同时拥有两者有点不寻常。但假设这正是您要处理的内容,则对您的 oneliner 进行以下修改有效:

perl -pe '/^([-0-9]+), ([-0-9]+)/; $new = - 8; s/^([-0-9]+), ([-0-9]+)/, $new/;'

第一个正则表达式匹配第一个和第二个字段(当它们由数字和 - 组成时)。然后我们在正则表达式语法之外进行计算,最后我们用新计算的值替换第二个字段。

非常接近您的原始版本,同时允许您修改任意列:

perl -aF',\s*' -pe '$F[1] =~ s/^([-0-9]+)/ - 8/e; $_ = join(", ", @F);' file
  • -a 自动拆分为 @F
  • -F/,\s*/
  • $F[1] =~ s/^([-0-9]+)/ - 8/e; 替换第 2 列
  • $_ = join(", ", @F);@F 重新加入 $_ 以允许 -p 打印