В #! / Bin / bash. Команда Unix для получения даты первого дня недели в месяце

8

Я ищу прямые команды Unix, чтобы получить первое воскресенье следующего месяца, первый понедельник следующего месяца, первый вторник следующего месяца, первую среду следующего месяца и т. Д.

  1. Они понадобятся мне в полном формате даты (время не обязательно)

  2. Я могу получить числа, такие как 2, 3, 4 и т. Д. Так как я не хочу только цифры, они мне понадобятся в формате даты (включая день, месяц, год)

    $ NEXT_MONTH=`date +'%m %Y' -d 'next month'`
    $ echo $NEXT_MONTH
    04 2017
    
    $ NEXT_SUNDAY=`cal $NEXT_MONTH | awk 'NF==7 && !/^Su/{print $1;exit}'`
    $ echo $NEXT_SUNDAY
    2
    
  3. Эти даты мне понадобятся для отправки уведомлений в группу электронной почты.

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

$ firstofmonth=$(date -d '+1 months' '+%Y%m01')
20170401

$ firstsaturday=$(date -d "$firstofmonth" '+%Y-%m')-$((7 - \
                $(date -d "$firstofmonth" '+%u')     ))    
2017-04-1
Хима
источник

Ответы:

11

В ksh93:

$ printf '%(%F)T\n' 'next month, first Monday'
2017-04-03

bash, поскольку 4.2 теперь поддерживает a %(<format)Tв своем printfбуитине, но не может анализировать этот тип выражения даты.

Если вы должны были использовать это bashи хотели использовать это %(<format>)T, вы все равно могли бы сделать это без разветвления с чем-то вроде:

printf -v code '%(
  t=$((%s + (12 - %-H) * 60 * 60))
  increment=$((8 - %u))
  current_month=%m)T' -1
eval "$code"
until
  t=$((t + increment * 24 * 60 * 60)) # next Monday around mid-day
  printf -v code '%(date=%F month=%m)T' "$t"
  eval "$code"
  [ "$month" != "$current_month" ] # until be get to next month
do
  increment=7 # the first increment is the number of days
              # til Monday. Next increments are just a week.
done
echo "$date"
Стефан Шазелас
источник
#! / bin / bash. Я получаю следующую ошибку в bash $ printf '% (% F) T \ n' 'в следующем месяце, в первый понедельник' -bash: printf: `(': недопустимый символ формата
Hima
1
@ Хима, я сказал в ksh93 . bashявляется незаконченным клоном ksh (с некоторыми особенностями (t) csh и zsh и даже несколькими собственными). В последних версиях bashдобавлена ​​поддержка printf '%(format)T'from ksh93, но нет возможности разбирать спецификации даты такого рода. Замени свою чёлку на #! /path/to/ksh93 -.
Стефан
« bashэто незаконченный клон кш», - я всегда так чувствовал.
Тим Кеннеди
@Stephene, я попытался с помощью команды ниже, чтобы получить в следующем месяце в прошлую субботу $ cal 04 2017 | awk 'NF <= 7 {print $ 6}' | grep -v "^ $" | tail -1 28 Показывает число 28, но я ищу полную дату 28.04.2017, пожалуйста, подскажите, возможно ли это с ним.
Хима
9

Предполагая GNU date(для этого -dвы используете себя), и zsh-подобную оболочку для {1..7}:

$ for i in {1..7} ; do \
    LC_ALL=C date '+%Y-%m-%d %a' -d "$(date +%Y%m0${i}) next month" ; \
  done | awk '/Mon/ {print $1}'
2017-04-03

Замените на awk Monлюбой требуемый день недели (используйте, LC_ALL=Cчтобы получить английские названия месяцев независимо от локали пользователя). Кроме того, может быть лучше сохранить это в переменной, если вы будете запрашивать каждый день недели:

$ days=$(for i in {1..7} ; do \
           LC_ALL=C date '+%Y-%m-%d %a' -d "$(date +%Y%m0${i}) next month" ; \
         done)

$ for i in Mon Tue Wed Thu Fri Sat Sun ; do \
    echo "${days}" | awk "/${i}/"'{print $1}' ; \
  done
2017-04-03
2017-04-04
2017-04-05
2017-04-06
2017-04-07
2017-04-01
2017-04-02
parkamark
источник
Также в bash этот код возвращает в следующем месяце первое Солнце, Пн, Ср, Таким образом, Пт, Сб. Спасибо. Я думаю, я могу изменить эту команду, чтобы получить в следующем месяце последнее Солнце, Пн, Ср и т. Д. Позвольте мне попробовать это.
Хима
Привет, я попробовал следующую команду, чтобы получить в следующем месяце в прошлую субботу $ cal 04 2017 | awk 'NF <= 7 {print $ 6}' | grep -v "^ $" | tail -1 Показывает число 28, но я ищу полную дату, например, 28.04.2017, пожалуйста, предложите, если это возможно.
Хима
"для i в {1..7}; делать дату '+% Y-% m-% d% a' -d" $ (дата +% Y% m01 -d '2 месяца') $ {i} дней назад "; done | awk '/ Sat / {print $ 1}'" - это даст 2017-04-29, то есть последнюю субботу следующего месяца. Этот код переходит на 2 месяца вперед до первого дня этого месяца, а затем возвращается на 1-7 дней, чтобы получить данные за последние 7 дней за предыдущий месяц. Я бы лично не использовал cal, так как я пробовал другие примеры здесь, и ни одна из них не работает на моей версии (CentOS 6).
parkamark
2

PHP на самом деле позволяет довольно просто анализировать даты с помощью ввода текста, если он доступен в вашей системе.

Пример:

bash-[522]$ php -qr 'date_default_timezone_set("UTC"); echo date("d-m-Y\n", strtotime("first monday of next month"));'
03-04-2017

У меня есть эта функция в моем .bashrc:

get_date ()
{
    text="$*";
    php -qr "date_default_timezone_set(\"UTC\"); echo date(\"d-m-Y\n\", strtotime(\"$text\"));"
}

Который я могу использовать как:

bash-[523]$ get_date first monday of next month
03-04-2017

Редактировать Добавление опции для использованияcal

Почти каждая система, которая имеет, bashбудет иметь cal. Программа календаря. Вы можете получить список на дату первого числа каждого дня недели, выполнив комбинацию cal, dateи awk, следующим образом :

 cal -hN $(date -d 'next month' +%b' '%Y) | grep -v $(date -d 'next month' +%b) | awk -v date=$(date -d 'next month' +%Y-%m-) '{ printf "%s: "date"%02i\n", $1, $2; }'

Который даст вам следующий вывод:

Su: 2017-04-02
Mo: 2017-04-03
Tu: 2017-04-04
We: 2017-04-05
Th: 2017-04-06
Fr: 2017-04-07
Sa: 2017-04-01

Изменение $2к $NFв заявлении AWK , чтобы получить дату последнего совпадения каждый день в течение месяца.

Тим Кеннеди
источник
Не работает в bash, $ php -qr 'date_default_timezone_set ("UTC"); дата эха ("dmY \ n", strtotime ("первый понедельник следующего месяца")); ' -bash: php: команда не найдена. пожалуйста, дайте мне знать, как это сделать в bash. а также, команда получить в следующем месяце последнее Солнце через Сб. Я пробовал, кое-как, как он выдает ошибки. Спасибо ..!!
Хима
Средства, которые вы не phpустановили. Я обновил с примером , который использует cal, dateи awkкоманду.
Тим Кеннеди
Я попробовал эту команду и выдает ошибку. Спасибо.!! $ cal -hN $ (дата -d 'следующий месяц' +% b ''% Y) | grep -v $ (дата -d 'следующий месяц' +% b) | awk -v date = $ (date -d 'следующий месяц' +% Y-% m-) '{printf "% s:" date "% 02i \ n", $ 1, $ 2; } 'cal: неверный параметр - h использование: cal [-13smjyV] [[месяц] год]
Hima