我有一个带有一些格式行的输入文件 -
此处为任意文本 {{x1 x2} {x3 x4}} 此处为任意文本
其中,x1、x2、x3 和 x4 是浮点数和/或整数。有没有办法通过使用 awk/perl/bash 脚本将这些数字中的每一个(总是括在花括号内)加倍?
我尝试使用以下变体,但我是 awk 的新手,甚至无法隔离花括号内的数字 -
awk -F( '{gsub("{}", " ", $NF); 打印 $NF}'
例子 -
输入:
此处为任意文本 1 {{1 2} {3 4}} 此处为任意文本 1
此处为任意文本 2 {{2.0 4} {6.0 8}} 此处为任意文本 2
此处为任意 text2p5
此处为任意 text3 {{3 6} {9 12}} 此处为任意 text3
此处为任意 text4 {{4 8} {12 16}} 此处为任意 text4
输出:
此处为任意文本 1 {{2 4} {6 8}} 此处为任意文本 1
此处为任意文本 2 {{4.0 8} {12.0 16}} 此处为任意文本 2
此处为任意 text2p5
此处为任意 text3 {{6 12} {18 24}} 此处为任意 text3
此处为任意 text4 {{8 16} {24 32}} 此处为任意 text4
您可以捕获所需的模式并使用它们的替换来重写字符串。
这是一个基本方法:首先捕获组件,处理它们,然后重新组装
use warnings;
use strict;
my $str = 'Arbitrary text here {{1 2} {3 4}} arbitrary text here';
my @parts = $str =~ /(.*?){{(\d+) (\d+)} {(\d+) (\d+)}}(.*)/;
# If we expect only lines in the above format test and handle the error
if (@parts != 6) {
die "Didn't find expected patterns in: $str";
}
my $pre_text = shift @parts;
my $post_text = pop @parts;
my ($r1, $r2, $r3, $r4) = map { $_*2 } @parts;
my $result = $pre_text . "{{$r1 $r2}{$r3 $r4}}" . $post_text;
print $result, "\n";
该代码假定输入的确切格式如图所示。这种“手动”、循序渐进的方法的一个优点是,可以更轻松地根据需要调整流程的每个部分。
这可以在一个正则表达式中完成。由于盲目相信预期的数据格式通常是一个非常糟糕的主意,我们可以将替换代码放在子中,以便可以检查匹配并根据需要更轻松地调整处理
sub repl {
my @nums = @_;
die "Expected four numbers, got: @nums" if @nums != 4;
my ($r1, $r2, $r3, $r4) = map { $_ * 2 } @nums;
return "{{$r1 $r2} {$r3 $r4}}";
}
$str =~ s/{{(\d+) (\d+)} {(\d+) (\d+)}}/repl($1, $2, $3, $4)/e;
这也大大清理了正则表达式本身。
如果模式不匹配,则什么都不会发生并$str
保持不变。如果我们只期望这种格式的行,那么我们可能想知道失败的匹配。了解它的一种方法是
if (not $str =~ s/.../) { warn "Failed match on: $str" }
因为替换运算符s/
返回所做的替换数。
更新提供的输入示例
上面的单正则表达式方法,带有input.txt
输入行的文件
use warnings;
use strict;
my $file = 'input.txt';
open my $fh, '<', $file or die "Can't open $file: $!";
while (<$fh>) {
s/{{(\d+) (\d+)} {(\d+) (\d+)}}/repl($1, $2, $3, $4)/e;
print;
}
sub repl {
my @nums = @_;
die "Expected four numbers, got: @nums" if @nums != 4;
my ($r1, $r2, $r3, $r4) = map { $_ * 2 } @nums;
return "{{$r1 $r2} {$r3 $r4}}";
}
印刷
此处任意文本1 {{2 4} {6 8}} 此处 任意文本1 此处任意文本2 {{4 8} {12 16}} 此处 任意文本2 此处 任意文本2p5 此处任意文本3 此处{{6 12} {18 24}} 任意文本3这里 任意 text4 这里 {{8 16} {24 32}} 这里任意 text4
die ...
潜艇中的线只是为了保护它,也许还有其他用途。在我们使用它的正则表达式中,除非找到所有四个匹配项,否则 sub 永远不会被调用。
上面的第一种方法,将该代码放置在输入行上的循环中,打印出相同的内容。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句