perl将H:MM:SS转换为MM.MMMM

perl将H:MM:SS转换为MM.MMMM,perl,Perl,我需要使用perl从文本文件DOW YYYY-MM-DD H:MM:SS.S中读入,然后输出十进制分钟数MM.MMMM。给定输入文本文件 Fri 2013-06-14 0:59:15.3 Sat 2013-06-15 1:01:30.6 Sun 2013-06-16 1:03:45.9 我想计算十进制的分钟数 (60*0)+59+(15.3/60) = 59.2550 (60*1)+01+(30.6/60) = 61.5100 (60*1)+03+(45.6/60) = 63.7600 然后

我需要使用perl从文本文件DOW YYYY-MM-DD H:MM:SS.S中读入,然后输出十进制分钟数MM.MMMM。给定输入文本文件

Fri 2013-06-14 0:59:15.3
Sat 2013-06-15 1:01:30.6
Sun 2013-06-16 1:03:45.9
我想计算十进制的分钟数

(60*0)+59+(15.3/60) = 59.2550
(60*1)+01+(30.6/60) = 61.5100
(60*1)+03+(45.6/60) = 63.7600
然后输出

(59.2550, 61.5100, 63.7600)

假设文本文件上的每一行都是它自己的日期,并且您正在读取的文件位于同一目录下,名为
input.txt
,我会这样做:

use strict;
use warnings;

my @result = ();

{
  open (my $file, "<", "input.txt") or die "cannot open < input.txt: $!";
  while(<$file>){
    my @current = split(/:/,substr($_,15));
    push(@result, (60*$current[0]) + $current[1] + ($current[2]/60));
  }
}

print "(" . join(',',@result) . ")";
使用严格;
使用警告;
我的@result=();
{

open(my$file,“输入文件的格式不是很清楚,但这似乎产生了您想要的内容。它需要输入文件的路径作为命令行参数

use strict;
use warnings;

my @minutes;
while (<>) {
  push @minutes, $1*60 + $2 + $3/60 if /(\d+):(\d+):([\d.]+)/;
}

printf "(%s)\n", join ', ', map sprintf('%.4f', $_), @minutes;

首先,您必须捕获您的输入:

my $time = "Fri 2013-06-14 0:59:15.3";
$time =~ /(\d+?):(\d+?):(.+)$/  #The time captured in three components
my $hours   = $1;
my $minute  = $2;
my $seconds = $3;
描述您希望在行中匹配的内容。
$
表示将我的表达式锚定在行的末尾。
(..)
是捕获组。这些组捕获在我的正则表达式中匹配的内容,并通过
$1
$2
$3
变量使它们可用

如果您从未学习过正则表达式,您应该学习。正则表达式非常强大,您应该在上面的链接中阅读它们,或者尝试使用

现在,我已经捕获了我的各种时间片段(假设60秒分钟和60分钟小时),我现在可以进行计算:

my $time_in_seconds = ( $hours * 3600 ) + ( $minutes * 60 ) + $seconds;
my $time_in_minutes = $time_in_seconds / 60;
计算机上的除法存在精度问题,因为很难用小数点后的小数表示为基数2。因此,我更喜欢将其全部相乘,然后除以60

一旦你有时间,你需要以你想要的格式打印出来。这需要:

%9.4f
指定了格式。
f
表示这是一个浮点数(基本上是一个非整数)。
4
表示小数位数。
9
表示字段宽度,其中包括小数、小数另一侧的四个和减号。因此,这将允许宽度高达
-9999.999
,这就足够了

总而言之

#! /usr/bin/env perl
#
use warnings;
use strict;
use feature qw(say);

while ( my $time = <DATA> ) {
    chomp $time;
    $time =~ /(\d+?):(\d+?):(.+)$/;  #The time captured in three components
    my $hours    = $1;
    my $minutes  = $2;
    my $seconds  = $3;
    my $time_in_seconds = ( $hours * 3600 ) + ( $minutes * 60 ) + $seconds;
    my $time_in_minutes = $time_in_seconds / 60;
    printf qq(%9.4f\n), $time_in_minutes;
}

__DATA__
Fri 2013-06-14 0:59:15.3
Sat 2013-06-15 1:01:30.6
Sun 2013-06-16 1:03:45.9

看起来不错。

你应该使用词法文件句柄和三个参数打开。@simbabque很好,我只是根据你的好建议改进了我的答案,使代码更好…你还应该
使用严格的
使用警告
;检查
打开的成功情况
如果失败,请检查
是否打开
包含
$!
;并使用正则表达式
/:/
作为
split
@Borodin的第一个参数,谢谢。我理解其他事情的原因,但为什么使用正则表达式
/:/
作为
split
更好?@darkajax:因为它被用作正则表达式,但你引用它,最好是clear.
$1*24
应该是
$1*60
,因为小时->minute@doubleDown:你说得对。谢谢。$cat./eassed_01.txt Fri 2013-06-14 0:59:15.3 Sat 2013-06-15 1:01:30.6 Sun 2013-06-16 1:03:45.9$./convert_to_min_03.pl./eassed_01.txt$cat./eassed_01.txt Fri 2013-06-14 0:59:15.3 Sat 2013-06-15 1:01:30.6 Sun2013-06-16 1:03:45.9 Gregs Mac mini:scripts gregcoats$/转换为\u min\u 03.pl./经过的\u 01.txtI没有任何输出$cat./经过的\u 01.txt Fri 2013-06-14 0:59:15.3 Sat 2013-06-15 1:01:30.6 Sun 2013-06-16 1:03:45.9 Gregs Mac mini:scripts gregcoats$/转换为\u min\u\u 03.pl./经过的时间并非所有分钟都有60秒,所以你的答案可能是用你的方法离开一秒钟。
printf "%9.4f\n", $time_in_minutes;
#! /usr/bin/env perl
#
use warnings;
use strict;
use feature qw(say);

while ( my $time = <DATA> ) {
    chomp $time;
    $time =~ /(\d+?):(\d+?):(.+)$/;  #The time captured in three components
    my $hours    = $1;
    my $minutes  = $2;
    my $seconds  = $3;
    my $time_in_seconds = ( $hours * 3600 ) + ( $minutes * 60 ) + $seconds;
    my $time_in_minutes = $time_in_seconds / 60;
    printf qq(%9.4f\n), $time_in_minutes;
}

__DATA__
Fri 2013-06-14 0:59:15.3
Sat 2013-06-15 1:01:30.6
Sun 2013-06-16 1:03:45.9
$ ./test.pl 
  59.2550
  61.5100
  63.7650