Способ замены строки NA на последовательные даты linux - PullRequest
0 голосов
/ 28 мая 2020

Это CSV-файл, который я получил

2020-03-05,0,146541,118965,5766,88,35
2020-03-06,0,164740,136624,6284,108,42
MISSINGDATE,0,178189,151802,6767,118,44
2020-03-08,0,188518,162008,7134,130,50
2020-03-09,0,196618,171778,7382,166,51
MISSINGDATE,0,210144,184179,7513,247,54

Я пытаюсь заменить часть «MISSINGDATE» в столбце на соответствующую дату, что соответствует дате в предыдущей строке.

Я смог указать "MISSINGDATE" с помощью команды sed, но не нашел способа изменить его соответственно.

когда я сделал

sed -i "s/[MISSINGDATE]/[date that I want]//g" file 

, фиксировалась только дата NA на дату, которую я ввел ...

результат, который я хочу, будет

2020-03-05,0,146541,118965,5766,88,35
2020-03-06,0,164740,136624,6284,108,42
2020-03-07,0,178189,151802,6767,118,44
2020-03-08,0,188518,162008,7134,130,50
2020-03-09,0,196618,171778,7382,166,51
2020-03-10,0,210144,184179,7513,247,54

Ответы [ 2 ]

0 голосов
/ 29 мая 2020

Если gawk - ваш вариант, попробуйте следующее:

gawk '
BEGIN {
    FS = OFS = ","                              # set field separator
    prev_date = "1970-01-01"                    # initial value just in case
}
function nextdate(day, epoch) {
    gsub("-", " ", day)                         # replace "-" with " "
    epoch = mktime(day " 0 0 0")                # seconds since the epoch
    return strftime("%Y-%m-%d", epoch + 86400)  # add one day
}
{
    if ($1 == "MISSINGDATE" ) {                 # if the date is missing
        $1 = nextdate(prev_date)                # then use the prev_date + 1day
    }
    prev_date = $1                              # update prev_date
    print
}' file.csv

Результат:

2020-03-05,0,146541,118965,5766,88,35
2020-03-06,0,164740,136624,6284,108,42
2020-03-07,0,178189,151802,6767,118,44
2020-03-08,0,188518,162008,7134,130,50
2020-03-09,0,196618,171778,7382,166,51
2020-03-10,0,210144,184179,7513,247,54
0 голосов
/ 28 мая 2020

bash:

prev_date="1970-01-01"
while IFS=, read -ra fields; do
    if [[ ${fields[0]} == "MISSINGDATE" ]]; then
        fields[0]=$(date -d "$prev_date + 1 day" "+%F")
    fi
    (IFS=,; echo "${fields[*]}")
    prev_date=${fields[0]}
done < file.csv

Предполагая дату GNU.

Я бы склонился к perl здесь (но я не совсем готов для объяснения)

perl -MTime::Piece -MTime::Seconds -F, -sape '
    if ($F[0] eq "MISSINGDATE") {
        $prev += ONE_DAY;
        $F[0] = gmtime($prev)->ymd;
        $_ = join ",", @F;
    } else {
        $prev = Time::Piece->strptime($F[0], "%Y-%m-%d");
    }
' -- -prev=0 file.csv
...