分隔一个没有分隔符的字符串

时间:2014-06-10 12:59:00

标签: perl

我们可以使用索引值分隔字符串,以便可以分离包含组合字符的输入,并且最终输出将是可读的字符串。

Input = 20140610182213  
Expecting Output = 2014-06-10 18:22:13

6 个答案:

答案 0 :(得分:2)

我通常使用替代类似的任务:

my $input = '20140610182213';
$input =~ s/(....)(..)(..)(..)(..)(..)/$1-$2-$3 $4:$5:$6/;
print $input;

另一种可能性是使用substr

my $input = '20140610182213';
my @delims = ('-', '-', ' ', ':', ':');
substr $input, $_, 0, pop @delims for 12, 10, 8, 6, 4;
print $input;

答案 1 :(得分:1)

您可能希望unpack

my ( $year, $mon, $mday, $hour, $min, $sec ) = unpack "A4 A2 A2 A2 A2 A2", "20140610182213";

say "$year-$mon-$mday $hour:$min:$sec";

答案 2 :(得分:1)

让我们全部modern

use strict;
use warnings;
use feature qw(say);

my $input = "20140610182213";

$input =~ /(?<year>\d{4})
            (?<month>\d{2})
            (?<day>\d{2})
            (?<hour>\d{2})
            (?<minute>\d{2})
            (?<second>\d{2})/x;

say "$+{year}-$+{month}-$+{day} $+{hour}:$+{minute}:$+{second}";

我在这里使用命名的背引用。在Perl从很早开始,你总是有数字后引用,我可以用括号设置:

$input =~ /(\d{4})(\d{2})(\d{2})/;
my $year  = $1;
my $month = $2;
my $day   = $3;

每个括号分组都是后引用。这是直接从sed

在Perl 5.10中,现在可以使用命名的反向引用。它们的格式为(?<name>regex),其中name是后引用的名称,regex是正则表达式。要引用它们,请使用$+{name},其中name是您的后引用名称。

最大的好处是你现在有了背面参考的实际名称,你不必担心$2的含义:

$input =~ /(?<year>\d{4})(?<month>\d{2})(?<day>\d{2})/;
my $year  = $+{year};
my $month = $+{month};
my $day   = $+{day};

现在,我们在正则表达式中使用x标志。这允许我们有多行正则表达式:

$input =~ /(?<year>\d{4})
           (?<month>\d{2})
           (?<day>\d{2})/x;   #The /x flag

my $year  = $+{year};
my $month = $+{month};
my $day   = $+{day};

如果你不熟悉语法,一开始可能会有点困难。然而,关于这一点的一个好处是它记录了正在发生的事情,并使维护更容易。一旦你的眼睛适应光线,就很容易看到发生了什么并发现错误。


另一种可能性是使用Time::Piece将日期时间转换为Perl可以直接操作的内容:

use strict;
use warnings;
use feature qw(say);

use Time::Piece;

my $input = "20140610182213";

my $date_object = Time::Piece->strptime($input, "%Y%m%d%H%M%S");

printf "%04d-%02d-%02d %02d:%02d:%02d\n",
    $date_object->year,
    $date_object->mon,
    $date_object->mday,
    $date_object->hour,
    $date_object->minute,
    $date_object->second;

同样,正在发生的事情已有详细记录。您可以看到输入字符串是什么,并且您可以轻松地引用字符串的每个部分,甚至可以更改格式。如果你想要这个月的名字怎么办?使用$date_object->month

对于简单的解析并且再也不使用它,第一种方式可能是最好的。但是,通过使用Time::Piece,您现在可以查看两个日期之间的天数(例如,您的日期/时间戳的年龄?)。

答案 3 :(得分:1)

我认为使用与sprintf的全局pattrn匹配是最整洁的:

my $dt = sprintf '%s%s-%s-%s %s:%s:%s', '20140610182213' =~ /../g;
print $dt;

<强>输出

2014-06-10 18:22:13

答案 4 :(得分:0)

如果您希望分配给变量的值(例如$ y,$ m,$ d等)以供日后使用:

perl -E '($y,$m,$d,$H,$M,$S)="20140610182213"=~/(....)(..)(..)(..)(..)(..)/;say "$y-$m-$d $H:$M:$S"'

答案 5 :(得分:0)

只需使用Time::Piece

即可
use strict;
use warnings;

use Time::Piece;

my $string = "20140610182213";

my $date = Time::Piece->strptime($string, "%Y%m%d%H%M%S");

print $date->strftime("%Y-%m-%d %H:%M:%S"), "\n";

输出:

2014-06-10 18:22:13