Perl用字符串中的"x"替换数字,但仅在一个特定位置

Dav*_* W. 6 regex perl

我正在解析填充各种错误的日志文件.这些是网络错误,这意味着客户在格式化我们网站的日期时蠢蠢欲动.日志看起来像这样:

Error 123: Customer 2: Bad Date [17/12/2014]
Error 123: Customer 2: Bad Date [19/12/2014]
Error 123: Customer 1: Bad Date [123/23/222]
Error 123: Customer 2: Bad Date [null]
Error 123: Customer 6: Bad Date [12/14:]
Error 123: Customer 6: Bad Date [12/16:]
Run Code Online (Sandbox Code Playgroud)

现在,前两个对同一个客户来说真的是同一个错误.这两行,报告日期DD/MM/YYYY而不是YYYY/MM/DD,所以我不需要两次报告此错误.最后两行对于同一客户也是同样的错误.使用MM/DD和离开一年.null即使我之前报告过客户#2的错误日期错误,该日期也是另一个错误.在某个地方,他们正在通过一个空日期.

我想做的是用这种方式比较线条:

Error 123: Customer 2: Bad Date [xx/xx/xxxx]
Error 123: Customer 2: Bad Date [xx/xx/xxxx]
Error 123: Customer 1: Bad Date [xxx/xx/xxx]
Error 123: Customer 2: Bad Date [null]
Error 123: Customer 6: Bad Date [xx/xx:]
Error 123: Customer 6: Bad Date [xx/xx:]
Run Code Online (Sandbox Code Playgroud)

现在,很容易看出前两行和后两行真的是同一个错误.问题是如何使用正则表达式执行此操作.我想改变之间的所有数字[]x的,但我不想碰字符串的休息,所以我不希望错误或客户数转换成x.

我第一次尝试:

$error =~ s/(\[.*?)\d/$1x/g;
Run Code Online (Sandbox Code Playgroud)

但这只触及括号中的第一个数字.我已经尝试过没有非贪婪的限定符,但这只涉及最后一个角色.

我可以这样做:

$error =~ s/\d/x/g;
Run Code Online (Sandbox Code Playgroud)

但是,它会x破坏我的错误编号和客户编号,从而取代所有出现的数字.

我可以一遍又一遍地传递错误行,直到没有更换:

while ( my $error = <DATA> ) {
    chomp $error;
    while ( $error =~ s/(\[.*?)\d/$1x/ ) {
        1;
    }
    say qq(Error: "$error");
}
Run Code Online (Sandbox Code Playgroud)

但必须有一种方法可以做到这一点,而无需while多次循环循环.

有没有办法用a x,但只在两个方括号之间有效地替换所有出现的数字?

amo*_*mon 5

我会用这个解决方案:

$error =~ s{(\[ [^\]]+ \])}{
  (my $date = $1) =~ tr/0-9/x/;
  $date;
}ex;
Run Code Online (Sandbox Code Playgroud)

如果没有可重入的正则表达式引擎,这将无法在旧的perls中使用.显然,我错了.我试着用freshly-代码酿造的Perl 5.10.1,和它的工作就好了.

或者,您可以滥用左值substr:

if ($error =~ /\[/gc) {
  my $start  = pos $error;
  my $length = index($error, ']', $start) - $start;
  substr($error, $start, $length) =~ tr/0-9/x/;
}
Run Code Online (Sandbox Code Playgroud)