Saya perlu menambah tanggal dengan +1d berdasarkan waktu. Ini tampaknya sedikit di atas kepala saya, tetapi saya curiga itu bisa dilakukan dengan Perl atau bahkan mungkin awk. Untuk setiap stempel waktu dengan 0000, saya perlu menambah hari dengan +1.

Memasukkan:

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

Keluaran yang diharapkan:

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

Sepertinya awk dapat menambah tanggal tetapi pertanyaan saya adalah bagaimana cara saya hanya menambah tanggal pada baris dengan 0000 sambil tetap mencetak sisa baris yang tidak berubah?

-5
nooobeee 9 Januari 2021, 00:37

3 jawaban

Jawaban Terbaik

Solusi Perl ini menggunakan Time::Piece (yang termasuk dalam distribusi standar).

#!/usr/bin/perl
use strict;
use warnings;
use Time::Piece;
use Time::Seconds 'ONE_DAY';

my $regex = '(\d\d/\d\d/\d\d\d\d) (\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;
}

Cetakan

C:\Old_Data\perlp>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
2
Chris Charley 9 Januari 2021, 00:38

Catatan: Ini diawali dengan komentar teratas saya. Karena pertanyaan ini telah dibuka kembali, saya dapat memposting jawabannya di sini.

Untuk menambah hari, kita juga perlu menggulung bulan jika perlu.

Untuk itu, kita perlu mengetahui jumlah hari dalam sebulan.

Untuk mengetahuinya, kita juga perlu mengetahui apakah tahun ini adalah tahun kabisat (yaitu Februari memiliki 28 atau 29 hari). Rumus sudah tersedia dengan pencarian web.

Saya tidak yakin tentang format input Anda:

15,07/31/2020 0000,778,0,82

Apa itu 15? Saya berasumsi Anda hanya melewatinya.

Apa itu 0000,778,0,82? Saya berasumsi Anda bisa membandingkan angka pertama [sebagai teks] dengan 0000.


Berikut kode di perl. Saya telah mengkodekan seluruh algoritme tanpa ketergantungan apa pun pada pemasangan paket Perl tambahan atau penggunaan fungsi seperti mktime, dll. Saya telah mencoba membuat anotasi sebanyak mungkin:

#!/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 %s\n",$date,$time);
    }
}
1
Craig Estey 9 Januari 2021, 04:31

Dengan 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

Sebagai satu baris:

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

Keluaran:

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

Lihat: 8 Variabel Bawaan Awk yang Kuat – FS, OFS, RS, ORS, NR, NF, FILENAME, FNR

1
Cyrus 9 Januari 2021, 06:47