我的输入文件包含一些格式的行 -
这里的任意文字{{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
任意文字3 {{3 6} {9 12}}任意文字3
任意文字4 {{4 8} {12 16}}任意文字4
输出:
此处的任意文字1 {{2 4} {6 8}}任意文字1
此处的任意文字2 {{4.0 8} {12.0 16}}此处任意文字2
此处任意text2p5
任意文字3 {{6 12} {18 24}}任意文字3
任意文字4 {{8 16} {24 32}}任意文字4
答案 0 :(得分:1)
您可以捕获所需的模式并使用替换来重写字符串。
这是一个基本方法:首先捕获组件,处理它们,然后重新组装
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中, 这样就可以检查匹配并根据需要更容易地调整处理
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}}";
}
打印
Arbitrary text1 here {{2 4} {6 8}} arbitrary text1 here Arbitrary text2 here {{4 8} {12 16}} arbitrary text2 here Arbitrary text2p5 here Arbitrary text3 here {{6 12} {18 24}} arbitrary text3 here Arbitrary text4 here {{8 16} {24 32}} arbitrary text4 here
子中的行die ...
仅用于保护它,可能用于其他用途。在我们使用它的正则表达式中,除非找到所有四个匹配项,否则从不调用sub。
上面的第一种方法,将代码置于输入行的循环中,打印出相同的内容。
答案 1 :(得分:0)
以下是Ruby中的一个示例。
$ echo "Arbitrary text here {{1.22 -3.55} {6.77 1e66}} arbitrary text here" |
ruby -lane 'p $_[/^[^{]*/] <<
$_[/{.*}/].gsub!(/[^ {}]+/) {|f| f.to_f*2} <<
$_[/[^}]*$/]'
"Arbitrary text here {{2.44 -7.1} {13.54 2.0e+66}} arbitrary text here"
Perl:
$ echo "Arbitrary text here {{1.22 -3.55} {6.77 1e66}} arbitrary text here" |
perl -lane '$lh = $1 if m/(^[^{]*)/;
$rh = $1 if m/([^}]*)$/;
$tgt = $1 if m/(\{.*\})/;
$tgt =~ s/([^{} ]+)/$1*2/ge; # the "e" executes the sub as Perl code
print "$lh$tgt$rh\n";'
Arbitrary text here {{2.44 -7.1} {13.54 2e+66}} arbitrary text here
这里的两种方法都是将开头{
和关闭}
视为'寻找浮动并用它做某事'行为的开始。例如,没有平衡括号的解析。如果在这种情况下是独立的,则Perl和Ruby都会将非数字视为0.0
,如果在数字字符串中,则将数字终止:
$ echo "Arbitrary text here {{1.22 -3.55 aa} {6s.77 1ye66}} arbitrary text here" |
perl -lane '$lh = $1 if m/(^[^{]*)/;
$rh = $1 if m/([^}]*)$/;
$tgt = $1 if m/(\{.*\})/;
$tgt =~ s/([^{} ]+)/$1*2/ge; # the "e" executes the sub as Perl code
print "$lh$tgt$rh\n";'
Arbitrary text here {{2.44 -7.1 0} {12 2}} arbitrary text here
这可能是也可能不是一个特征......
随你更新。同样适用于整数:
$ echo "Arbitrary text1 here {{1 2} {3 4}} arbitrary text1 here
Arbitrary text2 here {{2 4} {6 8}} arbitrary text2 here
Arbitrary text2p5 here
Arbitrary text3 here {{3 6} {9 12}} arbitrary text3 here
Arbitrary text4 here {{4 8} {12 16}} arbitrary text4 here" |
perl -lane '$rh=$lh=$tgt="";
$lh = $1 if m/(^[^{]*)/;
$rh = $1 if m/([^}]*)$/;
$tgt = $1 if m/(\{.*\})/;
$tgt =~ s/([^{} ]+)/$1*2/ge; # the "e" executes the sub as Perl code
if ($rh && $lh && $tgt) {
print "$lh$tgt$rh" ;
} else {
print $_;
}'
Arbitrary text1 here {{2 4} {6 8}} arbitrary text1 here
Arbitrary text2 here {{4 8} {12 16}} arbitrary text2 here
Arbitrary text2p5 here
Arbitrary text3 here {{6 12} {18 24}} arbitrary text3 here
Arbitrary text4 here {{8 16} {24 32}} arbitrary text4 here