Я пытаюсь манипулировать командой cal
для вывода в одну строку даты и чуть ниже дня недели, чтобы я мог использовать ее в excel для скрипта или html. Например.
Wed Thu Fri Sat Sun Mon Tue Wed
1 2 3 4 5 6 7 8
Использование bash
(или ksh93
), и GNU date
:
for (( i = 0; i < 8; ++i )); do
printf '%s\t' "$( date -d "now +$i days" +"%a" )"
done
echo
for (( i = 0; i < 8; ++i )); do
printf ' %d\t' "$( date -d "now +$i days" +"%e" )"
done
echo
Формат % a
даст вам сокращенный день недели в текущей локали, а % e
даст вам день месяц как целое число.
Результат (разделенные табуляцией):
Tue Wed Thu Fri Sat Sun Mon Tue
7 8 9 10 11 12 13 14
ОБНОВЛЕНИЕ для ksh93
после комментариев: (обратите внимание, это не работает, поскольку оболочка не проверяет даты должным образом)
#!/bin/ksh93
yearmonth=$( date +"%Y%m" )
d=1
while printf '%(%a)T\t' "$( printf '%s%02d' "$yearmonth" "$d" )" 2>/dev/null
do
(( ++d ))
done
echo
days_this_month=$(( --d ))
while (( d > 0 )); do
printf ' %d\t' "$(( days_this_month - (--d) ))"
done
echo
yearmonth
сначала устанавливается текущий год и месяц в формате YYYYMM
. Затем я перебираю все будние дни этого месяца. Цикл устанавливает wday
как сокращенный день недели, и он завершается, когда я пытаюсь получить день недели для недействительной даты.
Второй цикл просто печатает целые числа, столько, сколько нам нужно, чтобы заполнить месяц.
Вывод за февраль 2017 г .:
Wed Thu Fri Sat Sun Mon Tue Wed Thu Fri Sat Sun Mon Tue Wed Thu Fri Sat Sun Mon Tue Wed Thu Fri Sat Sun Mon Tue
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
Решение с использованием ksh93
с Perl и Date :: Calc :
#!/bin/ksh93
ym=( $(date +"%Y %m") )
days=$( perl -MDate::Calc -e 'print Date::Calc::Days_in_Month($ARGV[0],$ARGV[1])' -- "${ym[0]}" "${ym[1]}" )
for d in {1..$days}; do
printf '%(%a)T\t' "$( printf '%d-%d-%02d' "${ym[@]}" "$d" )"
done
echo
for d in {1..$days}; do
printf '%d\t' "$d"
done
echo
только с zsh
(только встроенные модули):
#! /bin/zsh -
zmodload zsh/datetime
now=$EPOCHSECONDS
strftime -s year %Y $now
strftime -s month %m $now
strftime -rs s %Y,%m,%d,%H $year,$month,1,12
output=()
while
for field (a d m) strftime -s $field %-$field $s
((month == m))
do
output+=($a $((d)))
((s += 86400))
done
print -C $(($#output / 2)) $output
только с bash
(4.2 или выше) (только встроенные модули), но при условии, что аббревиатуры дней недели состоят из 3 символов или меньше и состоят из однобайтовых символов только в вашей локали (поэтому не будут работать правильно во многих локалях, кроме английской).
#! /bin/bash -
printf -v now '%(%s)T' -1
printf -v d '%(%-d)T' "$now"
printf -v h '%(%-H)T' "$now"
printf -v month '%(%-m)T' "$now"
s=$((now +(12-h)*3600 - (d-1) * 86400))
l1= l2=
while
for field in a d m; do printf -v "$field" "%(%-$field)T" "$s"; done
((month == m))
do
printf -v l1 '%s%-3s ' "$l1" "$a"
printf -v l2 '%s%-3s ' "$l2" "$d"
((s += 86400))
done
printf '%s\n' "$l1" "$l2"
Вы также можете просто извлечь соответствующие строки непосредственно из cal выводит следующее:
>cal|sed -n '2p;/_/p'
Su Mo Tu We Th Fr Sa
5 6 7 8 9 10 11
(но обратите внимание, что cal будет использовать двухбуквенные сокращения дней недели, по крайней мере, в моей системе)
$ cal | perl -0ne '
if(/(.*)(Su.*?)\n(\h*)( 1.*?)\s*$/s){
$s= length($3);
$b=$2 x 5;
$n= $4 =~ s/[^\d ]//gr;
print substr($b,$s,length($n)),"\n$n\n" }'
We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
Объяснение: вывод cal делится на регулярное выражение (. *) (Su. *?) \ N (\ h *) (1. *?)
Febr 2017 \nSu Mo Tu We Th Fr Sa \n 1 2 3 4 \n 5 6 7 8 9 10 11 ...
($1 )($2 ) ($3 )($4 ... )
Используется $ 2
для построения полосы недель ( $ b = $ 2 x 5
) $ 4
используется для построения списка дней после удаления \ n
и выделения символов ( $ n = $ 4 = ~ s / [^ \ d] // gr
) $ 3
используется для удаления дней последнего месяца из полоса недель ( substr ($ b, $ s, length ($ n))
)