Скрипт bash и awk возвращает дату предыдущего месяца в формате ГГГГ-ММ-ДД - PullRequest
0 голосов
/ 04 мая 2018

Мне нужно получить дату последнего месяца в формате ГГГГ-ММ-ДД. Предположим, что если скрипт запускается в мае на какую-либо дату, он должен вернуть мне последнюю дату апреля месяца в формате 2018-04-30.

Would be good if can get the same work done with awk statement also.

Я попробовал код ниже и смог получить вывод в форме ниже, но мне нужно в формате ГГГГ-ММ-ДД

Apr 30 2018

Код:

#!/bin/bash
cur_month=`date +%m`
cur_year=`date +%Y`
prev_month=$(($cur_month-1))

# Check to see if this is January
if [ $prev_month -lt 1 ]
then
prev_year=$(($cur_year-1))
prev_month=12
LastDayOfpreviousMonth=`cal $prev_month $cur_year | grep -v "^$" | sed -n  '1p;$p' | tr "\n" " "  | awk '{print substr($1,1,3),$NF,$2}'`
else
LastDayOfpreviousMonth=`cal $prev_month $cur_year | grep -v "^$" | sed -n  '1p;$p' | tr "\n" " "  | awk '{print substr($1,1,3),$NF,$2}'`
fi
echo $LastDayOfpreviousMonth

Входной файл: в этом файле в столбце 14 необходимо указать значение даты за последний месяц в виде ГГГГ-ММ-ДД (2018-04-30)

EPOS|EPOS_OUTWARD_B2B_OSR_TTML_TTSL_$LDPM_20180504_V1.0.txt|||AD|Outward|ANP|Receipt cum invoice|42018|37AAACT2438A1ZS|INV|TAX|IN37201800001452|2018-04-17||||1||||SOHANRAJ RAJ KUMAR||||37||||||9984||Telecommunication services||||300|0||9|27|9|27|||||354||||||||||
EPOS|EPOS_OUTWARD_B2B_OSR_TTML_TTSL_$LDPM_20180504_V1.0.txt|||AD|Outward|ANP|Receipt cum invoice|42018|37AAACT2438A1ZS|INV|TAX|IN37201800001426|2018-04-12||||1||||MOLLITE SIVARAMA KRISHNA||||37||||||9984||Telecommunication services||||300|0||9|27|9|27|||||354||||||||||
EPOS|EPOS_OUTWARD_B2B_OSR_TTML_TTSL_$LDPM_20180504_V1.0.txt|||GJ|Outward|GUJ|Receipt cum invoice|42018|24AAACT2438A1ZZ|INV|TAX|IN24201800000651|2018-04-07||||1||||AIREN LTD ||||24||||||9984||Telecommunication services||||500|0||9|45|9|45|||||590||||||||||

Ответы [ 3 ]

0 голосов
/ 04 мая 2018

После awk предоставит вам последнюю дату последнего месяца в формате ГГГГ-ММ-ДД.

awk -v mon=$(date +%m) -v year=$(date +%Y) 'BEGIN{num=split("31,29,31,30,31,30,31,31,30,31,30,31",array,",");array[2]=year%4==0?29:28;for(i=1;i<=num;i++){a[i]=array[i]};prev=mon==1?12:mon-1;prev_year=mon==1?year-1:year;print year"-"prev"-"a[prev]}'  Input_file

Теперь добавляем не-лайнерную форму решения.

awk -v mon=$(date +%m) -v year=$(date +%Y) '
BEGIN{
  num=split("31,29,31,30,31,30,31,31,30,31,30,31",array,",");
  array[2]=year%4==0?29:28;
  for(i=1;i<=num;i++){
    a[i]=array[i]};
  prev=mon==1?12:mon-1;
  prev_year=mon==1?year-1:year;
  print year"-"prev"-"a[prev]
}'
0 голосов
/ 04 мая 2018

Хотя очевидно, что формат даты ОП основан на Unix, стоит упомянуть, что в игре есть два основных календаря. Юлианский календарь и Григорианский календарь . Оба календаря имеют разное представление о том, что такое високосный год.

примечание: в настоящее время большинство стран принимают григорианский календарь . Однако он не был официально принят всеми странами. Об этом следует помнить при проведении исторических исследований. Например, в Великобритании это изменение было внесено еще в 1752 г. н.э., а в Турции - не ранее 1927 г. (Ссылка на астрономические алгоритмы Жана Мееуса)

Имея это в виду и в зависимости от того, был ли ваш цифровой файл из Турции 1920 или 2011 года или Великобритании из 1740 или 1789 года, я представляю два awk решения

В високосном году месяц февраль имеет 29 дней, а в обычном году - 28 дней.

В юлианском календаре год является високосным (или биссекстильным) годом, составляющим 366 дней, если его числовое обозначение делится на 4. Все остальные годы являются обычными годами (365 дней).

Используя awk, так как это был запрос OP, мы можем написать следующую функцию, которая будет выполнять запрошенное преобразование:

awk 'function julian(str,    y,m,d) {
         y=substr(str,1,4); m=substr(str,6,2)+0;
         if (m==1) {y=y-1; m=12} else {m=m-1}
         if (((m-1)%7)%2==0) {d=31} else {d=30}
         if (m==2) { d = (y%4==0) ? 29 : 28 }
         return sprintf("%0.4d-%0.2d-%0.2d",y,m,d)
      }
      { print $14, julian($14) }' <file>

В григорианском календаре действует то же правило, что и в юлианском календаре, со следующим исключением: центориальные годы, которые не делятся на 400, являются общими годами.

awk 'function gregorian(str,    y,m,d) {
         y=substr(str,1,4); m=substr(str,6,2)+0;
         if (m==1) {y=y-1; m=12} else {m=m-1}
         if (((m-1)%7)%2==0) {d=31} else {d=30}
         if (m==2) { d = (y%4!=0) ? 28 : (y%100==0 && y%400!=0 ?  28 : 29 ) }
         return sprintf("%0.4d-%0.2d-%0.2d",y,m,d)
      }
      { print $14, gregorian($14) }' <file>

Поскольку календарь UNIX григорианский, мы также можем использовать GNU Awk Time Functions . Однако это будет работать только с 1970-02-01 по 2038-01-19 для 32-битных систем и 292277026596-04-01 для 64-битных систем (см. здесь )

awk 'function unix(str,    tmp) {
        tmp=substr(str,1,7)" 01 00 00 00"; gsub("-"," ",tmp);
        return strftime("%Y-%m-%d",mktime(tmp) - 1) }
     { print $14, unix($14) }' <file>
0 голосов
/ 04 мая 2018

Дата GNU сама по себе способна выполнить эту задачу идеально и надежно, не нужно никакой другой магии.

$ date -d "$(date +%Y-%m-01) - 1 day" "+%Y-%m-%d"
2018-04-30
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...