繁体   English   中英

Perl中有条件替换的正则表达式替换

[英]Regular Expression Substitution with Conditional Replacement in Perl

我的Perl技能非常初级,我正在尝试使用正则表达式替换(除其他外)将标量变量中加载的数据文件中的日期转换为四位数年份。

我有以下工作来使所有年份增加20。

$data00 =~ s/^D(\d{2})\/(\d{2})\/(\d{2})\n/D$1\/$2\/20$3\n/gm;

但是,日期包括2000年之前的日期。

在搜索解决方案时,我遇到了/ e选项,该选项表示它将替代项作为Perl代码进行评估。 但是,我在所有的文档中都没有找到它,我不确定语法是什么。

有没有一种方法可以评估$ 3的匹配项,如果$ 3小于50,则输出20,得出2000;如果不是19,则得出1997? 我选择50,因为它似乎是安全的中间立场。

出于说明目的,尽管我知道这是不正确的:

$data00 =~ s/^D(\d{2})\/(\d{2})\/(\d{2})\n/D$1\/$2\/(if($3<50)20 else 19)$3\n/eg;

/ e在这种情况下是否还合适?

从巨大的文本文件中提取的行示例。

D04/07/97
D04/14/98
D10/06/99
D10/13/05
D03/04/10
D12/09/10
D01/20/11
D12/22/11

使用/e ,替换表达式必须是有效的Perl表达式(即,您可以在$x =后面放置什么)。

您可以使用条件运算符( ?: :)根据条件对表达式进行不同的计算:

s/^D(\d{2})\/(\d{2})\/(\d{2})\n/ "D$1\/$2\/".( $3 < 50 ? 20 : 19 )."$3\n" /eg

请注意,如果涉及多个/ ,则替换定界符可以使内容更具可读性。

s{^D(\d{2})/(\d{2})/(\d{2})\n}{ "D$1/$2/".( $3 < 50 ? 20 : 19 )."$3\n" }eg

我会用Time :: Piece来做到这一点。 使用strptime()类方法将日期解析为一个对象,然后使用strftime()进行格式化。

#!/usr/bin/perl

use strict;
use warnings;
use feature 'say';
use Time::Piece;

while (<DATA>) {
  chomp;

  my $date = Time::Piece->strptime($_, 'D%m/%d/%y');

  say $date->strftime('D%m/%d/%Y');
}

__DATA__
D04/07/97
D04/14/98
D10/06/99
D10/13/05
D03/04/10
D12/09/10
D01/20/11
D12/22/11

输出:

D04/07/1997
D04/14/1998
D10/06/1999
D10/13/2005
D03/04/2010
D12/09/2010
D01/20/2011
D12/22/2011

可以通过a)选择其他定界符和b)使用三元运算符来简化正则表达式解决方案。 如果使用/e则替换文本在语法上需要有效的Perl。

while (<DATA>) {
  chomp;

  s|D(\d{2}/\d{2}/)(\d{2})|"D$1" . ($2 < 50 ? '20' : '19') . $2|e;

  say;
}

更新:两种解决方案之间有一个(可能是重要的)区别-20世纪和21世纪之间的界限是从两位数的年份转换为四位数的年份。 正则表达式解决方案使用50(如原始问题中所述)。 Time :: Piece解决方案使用69-该限制是硬编码的,因此无法更改它。 对于原始问题中的数据,这没有什么区别。 但是,如果您拥有的年份是1950年到1969年之间的数据,则可能会很重要。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM