perl bigint没有使用regexp匹配

时间:2017-07-26 14:31:48

标签: perl

我看到以下日志消息。通过查看数字,我怀疑timeStampLastSeekPoint总是一加timeInNanos

% grep -E '^java.lang.IllegalArgumentException.*timeStampLastSeekPoint' messages | head -5                              
java.lang.IllegalArgumentException: timeInNanos=1500629929661000010, timeStampLastSeekPoint=1500629929661000011
java.lang.IllegalArgumentException: timeInNanos=1500629929661000010, timeStampLastSeekPoint=1500629929661000011
java.lang.IllegalArgumentException: timeInNanos=1500629929661000010, timeStampLastSeekPoint=1500629929661000011
java.lang.IllegalArgumentException: timeInNanos=1500630763150000010, timeStampLastSeekPoint=1500630763150000011
java.lang.IllegalArgumentException: timeInNanos=1500630763150000010, timeStampLastSeekPoint=1500630763150000011

为了证实我的怀疑,我用这个perl单线管道来提取数字并显示差异。差异显示全0,这不可能是真的。很明显我需要更高的精度。

% grep -E '^java.lang.IllegalArgumentException.*timeStampLastSeekPoint' messages | \
    perl -ne 'if (/timeInNanos=(\d+), timeStampLastSeekPoint=(\d+)/) { printf("%ld %ld %ld\n", $1, $2, $2 - $1) }' | head -5      
1500629929661000010 1500629929661000011 0
1500629929661000010 1500629929661000011 0
1500629929661000010 1500629929661000011 0
1500630763150000010 1500630763150000011 0
1500630763150000010 1500630763150000011 0

我用Google搜索,找到bigint模块,然后尝试了。但是,它仍然无效。

% grep -E '^java.lang.IllegalArgumentException.*timeStampLastSeekPoint' messages | \
    perl -Mbigint -ne 'if (/timeInNanos=(\d+), timeStampLastSeekPoint=(\d+)/) { printf("%ld %ld %ld\n", $1, $2, $2 - $1) }' | head -5                                 
1500629929661000010 1500629929661000011 0                                                                                   
1500629929661000010 1500629929661000011 0
1500629929661000010 1500629929661000011 0
1500630763150000010 1500630763150000011 0
1500630763150000010 1500630763150000011 0

经过几次尝试后,我发现只有在将regexp匹配分配给常规变量后才能正常工作。顺便说一句,我现在证实我怀疑差异总是1。

% grep -E '^java.lang.IllegalArgumentException.*timeStampLastSeekPoint' messages | \
    perl -Mbigint -ne 'if (/timeInNanos=(\d+), timeStampLastSeekPoint=(\d+)/) { printf("%ld %ld %ld\n", $1, $2, ($b=$2) - ($a=$1)) }' | head -5                       
1500629929661000010 1500629929661000011 1                                                                                   
1500629929661000010 1500629929661000011 1
1500629929661000010 1500629929661000011 1
1500630763150000010 1500630763150000011 1
1500630763150000010 1500630763150000011 1                                                                                   

现在我找到了解决方法。但是,为什么分配是必要的并不直观。 $2 - $1不应该工作吗?感觉就像一个bug。或者,有没有解释才能理解这是一种合理的行为? perl版本是v5.14.2。

2 个答案:

答案 0 :(得分:0)

您的代码行为在perl 5.16和perl 5.18之间发生了变化。我没有进一步研究,以了解更改是修复还是实现。

$ PATH=/usr/local/ActivePerl-5.16/bin:$PATH

$ grep -E '^java.lang.IllegalArgumentException.*timeStampLastSeekPoint' messages |     perl -ne 'if (/timeInNanos=(\d+), timeStampLastSeekPoint=(\d+)/) { printf("%ld %ld %ld\n", $1, $2, $2 - $1) }' | head -5
1500629929661000010 1500629929661000011 0
1500629929661000010 1500629929661000011 0

$ PATH=/usr/local/ActivePerl-5.18/bin:$PATH

$ grep -E '^java.lang.IllegalArgumentException.*timeStampLastSeekPoint' messages |     perl -ne 'if (/timeInNanos=(\d+), timeStampLastSeekPoint=(\d+)/) { printf("%ld %ld %ld\n", $1, $2, $2 - $1) }' | head -5
1500629929661000010 1500629929661000011 1
1500629929661000010 1500629929661000011 1

答案 1 :(得分:0)

use bigint;对您的程序没有影响,因为它只影响数字文字,而您的程序没有。

use bigint;有效地用Math::BigInt->new("LITERAL")替换数字文字。这意味着

use bigint;

2

相当于

use Math::BigInt qw( );

Math::BigInt->new("2")

这提出了一个解决方案:

use Math::BigInt qw( );

Math::BigInt->new($2) - Math::BigInt->new($1)

但是由于重载运算符,你可以简单地使用

use Math::BigInt qw( );

Math::BigInt->new($2) - $1

use bigint;

0 + $2 - $1

在所有情况下,您希望使用%s(而非%d)让M :: BI字符串化数字 而不是将其编号为整数。