新手 Perl 家伙在這里。我有一個決議日志檔案的 Perl 腳本(v5.26.1)。由于我無法控制的原因,日志中每個日期的格式是這樣的:
"yyyy.mm.dd.hh.mm.ss"
例如:
"2022.09.19.16.35.00"
請注意,年始終是四位數字,而月、日、小時、分鐘和秒始終是兩位數。(例如九月是09)
我需要將此字串轉換為 DateTime 物件以進行比較。我認為這個練習會輕而易舉,但五個小時后,谷歌搜索了很多無果而終,而且我還沒有接近。這是我的第一次嘗試:
#!/usr/bin/perl
use warnings;
use strict;
sub transStrToDTime
{
# Example format of a date: "2022.09.19.16.35.00"
my $str = @_; # Only one input argument
use DateTime qw( );
my ($y,$m,$d,$h,$m,$s) = $str =~ /^([0-9]{4}).([0-9]{2}).([0-9]{2}).([0-9]{2}).([0-9]{2}).([0-9]{2})\z/
or die;
my $dt = DateTime->new(
year => $y,
month => $m,
day => $d,
hour => $h,
minute => $m,
second => $s,
time_zone => 'local'
);
printf("=-=-=-=-=-=-=->>> \"$dt\"\n");
}
my $str="2022.09.19.16.35.00";
transStrToDTime($str);
代碼有語法錯誤:
me@ubuntu:/home/me# ./toyPerl.pl
Died at ./toyPerl.pl line 16.
me@ubuntu:/home/me#
第 16 行是:
my ($y,$m,$d,$h,$m,$s) = $str =~ /^([0-9]{4}).([0-9]{2}).([0-9]{2}).([0-9]{2}).([0-9]{2}).([0-9]{2})\z/
Uggggggggghhhhhhhhhh...在閱讀了這個主題并變得更加困惑之后,我決定手動進行轉換。我想我所要做的就是:
split()上的字串.- 使用字串標記作為輸入構建一個新的 DateTime 物件:
這是嘗試:
#!/usr/bin/perl
use warnings;
use strict;
my $str="2022.09.19.16.35.00";
my @spl = split('.', $line);
#Lets look at the tokens before we build the DateTime object:
for(my $i = 0; $i <= $#spl; $i ){
print("$i) $spl[$i] \n");
}
輸出:
me@ubuntu:/home/me# ./toyPerl.pl
me@ubuntu:/home/me#
沒有輸出...意味著split()分成"2022.09.19.16.35.00" 零個標記? 是$str不是字串呢?那么它可能是什么資料型別呢?
#!/usr/bin/perl
use warnings;
use strict;
my $str="2022.09.19.16.35.00";
printf("Verifying that \$str is a string:\n");
printf("---> ${ref($str)}\n");
輸出:
me@ubuntu:/home/me# ./toyPerl.pl
Verifying that "2022.09.19.16.35.00" is a string:
Can't use string ("") as a SCALAR ref while "strict refs" in use at ./2222toyPerl.pl line 7.
me@ubuntu:/home/me#
第 7 行是這一行:
printf("---> ${ref($str)}\n");
我很混亂。錯誤訊息似乎說我的字串不是標量。但我認為字串在 Perl 中是標量的?(“標量通常是數字或字串。 ”)為什么""在第 7 行中將字串簡化為空字串 ( )?
天啊。這篇文章代表了半天的作業。誰能在第一種方法中發現我的語法錯誤?為什么我不能split()串"2022.09.19.16.35.00"?它不是一個字串或什么的嗎?謝謝你。
uj5u.com熱心網友回復:
當你放
my $str = @_;
這意味著您將陣列放在標量背景關系中,并且在標量背景關系中,陣列回傳它們的大小。你想要的是使用串列背景關系:
my ($str) = @_;
或者更好的是,使用慣用語shift:
my $str = shift; # automatically uses @_ inside a subroutine
您還使用了兩個$m變數。將其中一個更改為其他內容。修改后的代碼按預期作業:
use strict;
use warnings;
sub transStrToDTime {
my ($str) = @_; # Only one input argument
use DateTime qw( );
my ($y,$M,$d,$h,$m,$s) = $str =~ /^([0-9]{4}).([0-9]{2}).([0-9]{2}).([0-9]{2}).([0-9]{2}).([0-9]{2})\z/
or die;
my $dt = DateTime->new(
year => $y,
month => $M,
day => $d,
hour => $h,
minute => $m,
second => $s,
time_zone => 'local'
);
printf("=-=-=-=-=-=-=->>> \"$dt\"\n");
}
my $str="2022.09.19.16.35.00";
transStrToDTime($str);
輸出:
=-=-=-=-=-=-=->>> "2022-09-19T16:35:00"
您在第一種方法中稱為語法錯誤的東西實際上不是語法錯誤。只是您的代碼說明die正則運算式匹配是否失敗。請注意,die沒有訊息并不是非常有用。你可能想在那里放一些更有用的東西。
在第二種情況下,當您拆分時'.',您使用的是通配符.,而不是文字句點。因此,整個字串都被消耗掉了,什么都沒有了。你可以試試split /\./。
在第三種情況下,我不知道你在這里做什么:${ref($str)}你試圖從ref? from 的回傳值ref只是一個字串,例如ARRAYor SCALAR。這不是你使用的方式ref。如果您想知道變數包含什么,請改用Data::Dumper:
use Data::Dumper;
print Dumper $str;
# will print $VAR1 = 1; in your first program ($str is the size of the array @_)
另外,這一行:
printf("=-=-=-=-=-=-=->>> \"$dt\"\n");
printf可以使用的時候不要使用print。printf有特殊用途。- 不要在字串中轉義引號,而是考慮替代方案,例如:
printf " '%s' \n", $dt; # using printf correctly
print " '$dt' \n"; # more simple
print qq( "$dt" \n); # different delimiter
use feature 'say';
say " '$dt' "; # say includes newline at the end
uj5u.com熱心網友回復:
除了 TLP 所說的一切,您還可以使用
use DateTime::Format::Strptime qw( );
my $format = DateTime::Format::Strptime->new(
pattern => '%Y.%m.%d.%H.%M.%S',
strict => 1,
time_zone => 'local',
on_error => 'croak',
));
my $dt = $format->parse_datetime( $str );
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/513199.html
上一篇:測驗檔案句柄中的可用資料
