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
详情:
- -p 逐行读取文件并打印出来
- -e 运行 perl 代码,行内容在 $_
- s/.../.../e - 用表达式替换正则表达式
- ...^([-0-9]+) - 匹配任何数字 and/or - 符号。还捕获匹配的片段。
- $1 - 4.91 - 使用正则表达式捕获的值来完成工作。
文件示例。
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
打印
这适用于第一列。我怎么能把它改成只在第二个工作?我仍然可以在一行中完成它还是必须将其扩展为一个 .pl 文件?
列之间用逗号分隔 space ", "
perl -pe 's/^([-0-9]+)/ - 8/e' your_file > output.txt
详情:
- -p 逐行读取文件并打印出来
- -e 运行 perl 代码,行内容在 $_
- s/.../.../e - 用表达式替换正则表达式
- ...^([-0-9]+) - 匹配任何数字 and/or - 符号。还捕获匹配的片段。
- $1 - 4.91 - 使用正则表达式捕获的值来完成工作。
文件示例。
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
打印