【问题标题】:perl bigint not working with regexp matchesperl bigint 不适用于正则表达式匹配
【发布时间】:2017-07-27 03:27:24
【问题描述】:

我看到以下日志消息。通过查看数字,我怀疑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

我用谷歌搜索,找到了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

经过几次尝试,我发现它只有在将正则表达式匹配分配给常规变量后才有效。顺便说一句,我现在确认我的怀疑,即差异始终为 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。

【问题讨论】:

  • 顺便说一句,“%ld”中的“l”在 Perl 中毫无意义。

标签: perl


【解决方案1】:

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 将数字字符串化 而不是让它 numify 为一个整数。

【讨论】:

  • 感谢您的精彩解释。我不知道 use bigint 只影响数字文字。我很困惑($b=$2) - ($a=$1) 是如何解决它的(我刚刚确认它在没有-Mbigint 的情况下也可以工作)。我认为bigint 在分配期间发挥了作用。
【解决方案2】:

您的代码行为在 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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-10
    • 2018-11-13
    • 2016-06-29
    • 2020-02-19
    相关资源
    最近更新 更多