我试图在以下一组行上进行替换:
1AA20160817BBBBBDIGITS1NUMBER1STYLE59 00002200000220
1AA20160817BBBBBDIGITS2NUMBER1STYLE60 00000000000220
1AA20160817DDDDDDIGITS3NUMBER2STYLE60 00000000000486
1AA20160817DDDDDDIGITS4NUMBER2STYLE59 00004860000486
1AA20160817FFFFFDIGITS5NUMBER3STYLE602523111100000000000000
1AA20160817FFFFFDIGITS6NUMBER3STYLE59 00000820000000
我希望最终输出如下:
1AA20160817BBBBBDIGITS1NUMBER1STYLE59 00002200000220
1AA20160817BBBBBDIGITS1NUMBER1STYLE60 00000000000220
1AA20160817DDDDDDIGITS3NUMBER2STYLE60 00000000000486
1AA20160817DDDDDDIGITS3NUMBER2STYLE59 00004860000486
1AA20160817FFFFFDIGITS5NUMBER3STYLE602523111100000000000000
1AA20160817FFFFFDIGITS5NUMBER3STYLE59 00000820000000
更改是一位数,就在每秒的“数字”之前。 BBBBB / DDDDD样式的模式是时间,最后一个字符是秒指示符。
我希望它检查特定数量的字符并在那里执行更改,我写了sed来执行该任务及其类似:
sed -i.bak "s/^\(.\{1\}\)$scenario$datein\(.\{6\}\)$pod/1$scenario$datein$timein$pod/g" $1
其余代码在Perl中。你们中的一个可以帮我在Perl中做同样的替换吗?或者也许告诉我如何运行这个sed命令,从perl代码?我的问题是有问题的文件是巨大的,并且bash需要很长时间才能读取每一行,并执行替换。提前谢谢。
答案 0 :(得分:2)
假设您的输入数据位于data.txt
:
$ perl -i -pe's/(\d)(?=NUMBER)/$1-1/e if ! ($. % 2)' data.txt
-i
:就地编辑输入文件并创建备份-p
:在输入的每一行运行此代码并在每次迭代时打印$ _ -e
:要运行的代码s/(\d)(?=NUMBER)/$1-1/e
:找一个数字后跟“' NUMBER'并将其替换为从数字if ! ($. % 2)
:但只对偶数编号记录执行此操作答案 1 :(得分:0)
更新已清除substr
上的语句,这些语句指的是“号码”,考虑到发布的数据 - substr
有效用字符串。用更好的方法替换魔法22
以找到偏移量。
您可以通过查看$.
- 从(上次访问的)文件句柄读取的当前行号来识别偶数行和奇数行。见in perlvar
。
use warnings;
use strict;
my $set_num_to = 0;
while (<DATA>)
{
if ($. % 2 != 0) { # odd line number
($set_num_to) = $_ =~ m/(\d)NUMBER/;
print;
}
else {
s/\d(?=NUMBER)/$set_num_to/;
print;
}
}
__DATA__
1AA20160817BBBBBDIGITS1NUMBER1STYLE59 00002200000220
1AA20160817BBBBBDIGITS2NUMBER1STYLE60 00000000000220
1AA20160817DDDDDDIGITS3NUMBER2STYLE60 00000000000486
1AA20160817DDDDDDIGITS4NUMBER2STYLE59 00004860000486
1AA20160817FFFFFDIGITS5NUMBER3STYLE602523111100000000000000
1AA20160817FFFFFDIGITS6NUMBER3STYLE59 00000820000000
正则表达式使用字符串NUMBER
,如示例中所示,并且缺少更多细节,以识别要在奇数行上获取的数字,然后用于替换偶数位置上的数字线。它使用positive lookahead
,(?=PATTERN)
。如果替换应该比当前数字少一个(而不是前一行的数字),你可以使用
s/(\d)(?=NUMBER)/$1-1/e if $. % 2 == 0;
/e
修饰符首先评估替换方,然后将其结果用作替换方。请参阅perlop
和this post
。
如果位置固定,可以使用substr
my $offset = length '1AA20160817BBBBBDIGITS';
while (<DATA>)
{
if ($. % 2 != 0) {
# Retrieve substring of length 1 at given offset
$set_num_to = substr $_, $offset, 1;
}
else {
# Replace substring of same length at same offset by one captured above
substr $_, $offset, 1, $set_num_to;
}
}
其余部分相同,并按指定打印行。
同样,如果你需要从那里减去1而不是用前一行中的数字替换它,你可以在$. % 2 == 0
条件下使用上面的两行。