Как использовать bash для получения последнего дня каждого месяца для текущего года без использования if else или switch или while loop?
Как мы знаем, каждый год каждый следующий месяц должен иметь следующий максимальный день:
Jan - 31 days
Feb - 28 days / 29 days (leap year)
Mar - 31 days
Apr - 30 days
May - 31 days
Jun - 30 days
Jul - 31 days
Aug - 31 days
Sep - 30 days
Oct - 31 days
Nov - 30 days
Dec - 31 days
Как мне получить bash для возврата значения (последний день каждого месяца) за текущий год без использования циклов if else
или switch
или while
?
Ответы
Ответ 1
мой прием:
for m in {1..12}; do
date -d "$m/1 + 1 month - 1 day" "+%b - %d days";
done
Чтобы объяснить: для первой итерации, когда m = 1, аргумент -d
равен "1/1 + 1 месяц - 1 день" и "1/1" интерпретируется как 1 января. Итак, 1 января + 1 месяц - 1 день - 31 января. Следующая итерация "2/1" - 1 февраля, добавьте месяц, чтобы вычесть день, чтобы получить 28 или 29 февраля. И так далее.
Ответ 2
cat <<EOF
Jan - 31 days
Feb - `date -d "yesterday 3/1" +"%d"` days
Mar - 31 days
Apr - 30 days
May - 31 days
Jun - 30 days
Jul - 31 days
Aug - 31 days
Sep - 30 days
Oct - 31 days
Nov - 30 days
Dec - 31 days
EOF
Ответ 3
Предполагая, что вы разрешаете "для", затем следующее в bash
for m in {1..12}; do
echo $(date -d $m/1/1 +%b) - $(date -d "$(($m%12+1))/1 - 1 days" +%d) days
done
производит это
Jan - 31 days
Feb - 29 days
Mar - 31 days
Apr - 30 days
May - 31 days
Jun - 30 days
Jul - 31 days
Aug - 31 days
Sep - 30 days
Oct - 31 days
Nov - 30 days
Dec - 31 days
Примечание. Я удалил необходимость cal
Для тех, кто любит мелочи:
Number months from 1 to 12 and look at the binary representation in four
bits {b3,b2,b1,b0}. A month has 31 days if and only if b3 differs from b0.
All other months have 30 days except for February.
Итак, за исключением февраля это работает:
for m in {1..12}; do
echo $(date -d $m/1/1 +%b) - $((30+($m>>3^$m&1))) days
done
Результат:
Jan - 31 days
Feb - 30 days (wrong)
Mar - 31 days
Apr - 30 days
May - 31 days
Jun - 30 days
Jul - 31 days
Aug - 31 days
Sep - 30 days
Oct - 31 days
Nov - 30 days
Dec - 31 days
Ответ 4
cal $(date +"%m %Y") | awk 'NF {DAYS = $NF}; END {print DAYS}'
Ответ 5
возвращает количество дней в месяце, компенсирующих февральские изменения в високосные годы без цикла или использования оператора if и только один раз называет дату.
Этот код проверяет дату, чтобы увидеть, действительно ли 29 февраля запрошенного года, если это так, то он обновляет второй символ в строке смещения дня. Аргумент месяца выбирает соответствующую подстроку и добавляет разницу в месяц к 28.
function daysin()
{
s="303232332323" # normal year
date -d "2/29/$2" > /dev/null 2>&1 && s="313232332323" # leap year
echo $[ ${s:$[$1-1]:1} + 28 ]
}
daysin $1 $2 #daysin [1-12] [YYYY]
Ответ 6
Попробуйте использовать этот код
date -d "-$(date +%d) days month" +%Y-%m-%d
Ответ 7
Содержание script.sh
:
#!/bin/bash
begin="-$(date +'%-m') + 2"
end="10+$begin"
for ((i=$begin; i<=$end; i++)); do
echo $(date -d "$i month -$(date +%d) days" | awk '{ printf "%s - %s days", $2, $3 }')
done
Результаты:
Jan - 31 days
Feb - 29 days
Mar - 31 days
Apr - 30 days
May - 31 days
Jun - 30 days
Jul - 31 days
Aug - 31 days
Sep - 30 days
Oct - 31 days
Nov - 30 days
Ответ 8
На Mac, который показывает дату BSD, вы можете просто:
for i in {2..12}; do date -v1d -v"$i"m -v-1d "+%d"; done
Быстрое пояснение
-v
означает настройку. Мы корректируем дату:
-v1d
означает первый день месяца
-v"$i"m
определен месяц, например. (-v2m
за февраль)
-v-1d
минус один день (так что мы получаем последний день предыдущего месяца)
"+%d"
распечатать день месяца
for i in {2..12}; do date -v1d -v"$i"m -v-1d "+%d"; done
31
28
31
30
31
30
31
31
30
31
30
Вы можете добавить год, конечно. См. Примеры в man-странице (ссылка выше).
Ответ 9
for m in $(seq 1 12); do cal $(date +"$m %Y") | grep -v "^$" |tail -1|grep -o "..$"; done
- итерация от 1 до 12 (для...)
- распечатать таблицу календаря для каждого месяца (cal...)
- удалить пустые строки из вывода (grep -v...)
- напечатать последний номер в таблице (хвост...)
Нет смысла избегать использования cal, потому что это требуется POSIX, поэтому должно быть там