我需要根据时间将日期增加+1d。这似乎有点让我难以理解,但我怀疑它可以用perl甚至awk来完成。对于每个包含0000的时间戳,我需要将日期增加+1。
输入:
15,07/31/2020 1600,1048,31,0
15,07/31/2020 1700,1086,45,0
15,07/31/2020 1800,1092,42,0
15,07/31/2020 1900,1017,20,1
15,07/31/2020 2000,945,0,28
15,07/31/2020 2100,897,0,43
15,07/31/2020 2200,869,0,55
15,07/31/2020 2300,812,0,72
15,07/31/2020 0000,778,0,82
预期输出:
15,07/31/2020 1600,1048,31,0
15,07/31/2020 1700,1086,45,0
15,07/31/2020 1800,1092,42,0
15,07/31/2020 1900,1017,20,1
15,07/31/2020 2000,945,0,28
15,07/31/2020 2100,897,0,43
15,07/31/2020 2200,869,0,55
15,07/31/2020 2300,812,0,72
15,08/01/2020 0000,778,0,82
看起来awk可以增加日期,但我的问题是,我如何只增加0000行的日期,同时仍然打印出其余行?
这个Perl解决方案使用Time::Piece(包含在标准发行版中(。
#!/usr/bin/perl
use strict;
use warnings;
use Time::Piece;
use Time::Seconds 'ONE_DAY';
my $regex = '(dd/dd/dddd) (d{4})';
while (<>) { # reads from the input file supplied on the CLI
my ($mdy, $time) = /$regex/;
if ($time eq '0000') {
# parse the date ($mdy) and add 1 day
my $date = Time::Piece->strptime($mdy, "%m/%d/%Y") + ONE_DAY;
# convert the Time::Piece object to a string rep
$date = $date->strftime("%m/%d/%Y");
# substitute the new date for the date 1 day earlier
s/$regex/$date $time/;
}
print;
}
打印
C:Old_Dataperlp>perl test3.pl f0.txt
15,07/31/2020 1600,1048,31,0
15,07/31/2020 1700,1086,45,0
15,07/31/2020 1800,1092,42,0
15,07/31/2020 1900,1017,20,1
15,07/31/2020 2000,945,0,28
15,07/31/2020 2100,897,0,43
15,07/31/2020 2200,869,0,55
15,07/31/2020 2300,812,0,72
15,08/01/2020 0000,778,0,82
注意:这是我的顶部评论。既然这个问题已经重新开始,我可以在这里发布答案。
为了增加日期,如果必要的话,我们还需要将月份展期。
为此,我们需要知道一个月中的天数。
要知道这一点,我们还需要知道当前年份是否是闰年(即二月有28天或29天(。这个公式很容易通过网络搜索获得。
我不确定你输入的格式:
15,07/31/2020 0000,778,0,82
什么是15
?我想你只是通过它。
什么是0000,778,0,82
?我想你可以将第一个数字[作为文本]与0000
进行比较。
这是perl
中的代码。我已经对整个算法进行了编码,而不依赖于安装额外的perl包或使用mktime
等函数
#!/usr/bin/perl
# code to increment day
master(@ARGV);
exit(0);
sub master
{
my(@days_in_month) = (31,28,31,30,31,30,31,31,30,31,30,31);
# input format:
# 15,07/31/2020 0000,778,0,82
while ($buf = <STDIN>) {
chomp($buf);
# split off date and time
my($date,$time) = split(" ",$buf);
# split up date
my($pre,$mon,$day,$year) = split(m%[,/]%,$date);
# decide if current year is leap year
my($isleap) = 0;
{
# year must be divisible by 4
last if (($year % 4) != 0);
# if year is divisible by 100, it is _not_ a leap year unless ...
if (($year % 100) == 0) {
# ... it is also divisible by 400
last if (($year % 400) != 0);
}
$isleap = 1;
}
# get number of days in february
if ($isleap) {
$days_in_month[1] = 29;
}
else {
$days_in_month[1] = 28;
}
# change only if time is 0000
if ($time =~ /^0000,/) {
# increment day
$day += 1;
# advance month if necessary
if ($day > $days_in_month[$mon - 1]) {
$day = 1;
$mon += 1;
}
# advance year if necessary
if ($mon > 12) {
$mon = 1;
$year += 1;
}
}
$date = sprintf("%2.2d,%2.2d/%2.2d/%4.4d",$pre,$mon,$day,$year);
printf("%s %sn",$date,$time);
}
}
使用GNU awk:
awk '$5=="0000"{
# convert columns to unixtime
unixtime=mktime($4 " " $2 " " $3 " " "00 00 00")
# add one day to unixtime and convert back to month/day/year
nextday=strftime("%m/%d/%Y",unixtime+60*60*24)
# rebuild current row
$0=$1 OFS nextday " " $5 OFS $6 OFS $7 OFS $8
}
{print}' FS='[,/ ]' OFS=',' file
作为一行:
awk '$5=="0000"{unixtime=mktime($4 " " $2 " " $3 " " "00 00 00"); nextday=strftime("%m/%d/%Y",unixtime+60*60*24); print $1,nextday " " $5,$6,$7,$8; next}{print}' FS='[,/ ]' OFS=',' file
输出:
2020年7月31日15时,16001048,31,02020年7月31日15日17001086,45,02020年7月31日星期五18001092,42,02020年7月31日星期五19001017,20,12020年7月15日,邮编:2000945,0,282020年7月31日15日2100897,0,432020年7月31日15日2200869,0.552020年7月31日星期五2300812,0,722020年1月15日0000778,0,82
请参阅:8个强大的Awk内置变量–FS、OFS,RS、ORS、NR、NF、FILENAME、FNR-