[英]Perl ignore whitespace on replacement side of regular expression substitution
[英]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.