Відображення номера тижня у певному форматі за допомогою ncal або cal


16

Ви не просто любите це, коли дві команди виконують одну потрібну вам річ, але ні обидві?

Це те, що calробить. Приємне форматування. Не вистачає тижневих цифр:

$ cal
    January 2012      
Su Mo Tu We Th Fr Sa  
 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  
29 30 31              

Це те, що ncalробить. Дивне форматування, але з номерами тижнів:

$ ncal -w
    January 2012      
Su  1  8 15 22 29   
Mo  2  9 16 23 30   
Tu  3 10 17 24 31   
We  4 11 18 25      
Th  5 12 19 26      
Fr  6 13 20 27      
Sa  7 14 21 28      
    1  2  3  4  5   

Який вихід я хочу, насправді є схрещуванням між calта ncal -w:

$ cal --magik-calendar-week-option
      January 2012      
   Su Mo Tu We Th Fr Sa  
1   1  2  3  4  5  6  7  
2   8  9 10 11 12 13 14  
3  15 16 17 18 19 20 21  
4  22 23 24 25 26 27 28  
5  29 30 31

Відповіді:


13

Якщо жодна з цих команд не відповідає вашим потребам, ви можете gcalзамість цього робити те, що хочете.

Приклад

$ gcal -K

      April 2014
 Su Mo Tu We Th Fr Sa CW
        1  2  3  4  5 13
  6  7  8  9 10 11 12 14
 13 14 15 16 17 18 19 15
 20 21 22 23 24 25 26 16
 27 28 29 30          17

Друкує номер тижня в останньому стовпчику праворуч.

Список літератури


gcal --starting-day=Monday --with-week-numberбільше відповідає моїм потребам, але цей інструмент чудовий.
k0pernikus

9

Це підкреслює сьогоднішню дату і може відображати будь-який місяць через $1форму: YYYY-mm-dd... Він за замовчуванням відповідає сьогоднішній даті

Він створений, щоб показувати номери тижнів ISO, а перший тиждень - понеділок.

#!/bin/bash
# Input reference date is expected in  'YYYY-mm-dd' format
#
today=($(date '+%Y %m %d')); Y=0; m=1; d=2                # establish today's date
[[ -z $1 ]] && ref=(${today[@]}) || ref=(${1//-/ })       # get input date
dNbA=$(date --date="$(date +%Y-%m-01)" +'%u')             # day-number of 1st day of reference month
today[m]=$((10#${today[m]})); ref[m]=$((10#${ref[m]}))    # remove leading zero (octal clash)
today[d]=$((10#${today[d]})); ref[d]=$((10#${ref[d]}))    # remove leading zero (octal clash)
nxtm=$(( ref[m]==12 ?1       :ref[m]+1 ))                 # month-number of next month
nxtY=$(( ref[m]==12 ?ref[Y]+1:ref[Y]   ))                 # year-number of next month
nxtA="$nxtY-$nxtm-1"                                      # date of 1st day of next month
refZ=$(date --date "$(date +$nxtA) yesterday" +%Y-%m-%d)  # date of last day of reference  month
days=$(date --date="$refZ" '+%d')                         # days in reference month

h1="$(date --date="${ref[Y]}-${ref[m]}-${ref[d]}" '+%B %Y')" # header 1 
h2="Mo Tu We Th Fr Sa Su"                                    # header 2 
printf "    %$(((${#h2}-${#h1}-1)/2))s%s\n" " " "$h1"
printf "    %s\n" "$h2"
# print week rows   
printf "%2d  " "$((10#$(date -d "$(date +${ref[Y]}-${ref[m]}-01)" +'%V')))" # week-number (of year) with suppressed leading 0
printf "%$(((dNbA-1)*3))s"  # lead spaces (before start of month)
dNbW=$dNbA  # day-number of week
dNbM=1      # day-number of month
while ((dNbM <= days)) ;do
    if (( today[Y]==ref[Y] &&  
          today[m]==ref[m] && 
          today[d]==dNbM )) ;then
        printf "\x1b[7m%2d\x1b[0m " "$dNbM" # highlight today's date 
    else
        printf "%2d " "$dNbM"
    fi
    ((dNbM++))
    if ((dNbW  >=7)) ;then
        cdate=$((10#$(date -d "$(date +${ref[Y]}-${ref[m]}-$dNbM)" +'%V'))) # remove leading zero (octal clash)
        printf "\n%2d  " "$cdate" # week-number of year
        dNbW=0
    fi
    ((dNbW++))
done
printf "%$(((8-dNbW)*3))s\n" # trailing spaces (after end of month)

Ось показ цього місяця (з 20виділеним)

       January 2012
    Mo Tu We Th Fr Sa Su
52                     1 
 1   2  3  4  5  6  7  8 
 2   9 10 11 12 13 14 15 
 3  16 17 18 19 20 21 22 
 4  23 24 25 26 27 28 29 
 5  30 31                

Я навіть не помітив ізопроблему. Це зробить :)
k0pernikus

1
@ k0pernikus: Я щойно змінив сценарій .. (приблизно через 35 хвилин після того, як ви опублікували вищевказаний коментар) .. Це захопилося 08і 09інтерпретується як восьмеричний, а не десятковий . Це має бути добре зараз ...
Пітер.О

7

Ви можете використовувати nlдля нумерації рядків (це і є ціль програми :). Але потрібно витягти перший тиждень у місяці звідкись. Це можна зробити з ncalсебе:

$ ncal -w 2 2012 | tail -1 | awk '{print $1}'
5

Ми вставляємо це як параметр до параметра nl's -v(номер початкового рядка) і повідомляємо його лише числовим рядкам з цифрами або пробілами.

$ cal 2 2012 | nl -bp'^[0-9 ]\+$' -w2 -s'  ' -v$(ncal -w 2 2012 | tail -1 | awk '{print $1}')
       February 2012
    Su Mo Tu We Th Fr Sa
 5            1  2  3  4
 6   5  6  7  8  9 10 11
 7  12 13 14 15 16 17 18
 8  19 20 21 22 23 24 25
 9  26 27 28 29

Це все дуже жахливо. У будь-якому випадку, якщо вам не знадобляться calбільш вдосконалені варіанти, це спрацює. Ви можете помістити його у файл і замінити "$@"там, де я поклав 2 2012.


EDIT: Але це НЕПРАВНО! Я щойно помітив, що перший тиждень січня може мати число 52 чи 53! Таким чином, ми просто повинні зробити виняток за січень, або просто витягнути всі номери тижня ncalі застосувати їх до результату cal.

Це рішення, про яке я думав спочатку, але думав (помилково), що спрощую його за допомогою nl. Він використовує paste, що об'єднує файли поруч. Оскільки не існує жодного файлу, ми повинні використовувати башизм <(...); саме цього я намагався уникати.

Першим нашим "файлом" буде список номерів тижнів, на початку два порожні рядки:

$ printf '   \n   \n' && printf '%2d \n' $(ncal -w 1 2011 | tail -1)


52
 1
 2
 3
 4
 5

Другий, тільки вихід cal. Все разом, як параметри для paste:

$ paste -d' ' <(printf '   \n   \n' && printf '%2d \n' $(ncal -w 1 2011 | tail -1)) <(cal 1 2011)
        January 2011
    Su Mo Tu We Th Fr Sa
52                     1
 1   2  3  4  5  6  7  8
 2   9 10 11 12 13 14 15
 3  16 17 18 19 20 21 22
 4  23 24 25 26 27 28 29
 5  30 31

Набагато сильніше і несумісніше, ніж інше. Закінчується ...


Не так здорово: - /. Дивіться мою редакцію.
angus

7

Створіть послідовність тижнів з ncalта використовуйте pasteдля того, щоб обидва виходи були поруч.

$ paste <(echo; echo; ncal -w | tail -1 | xargs -n1 printf '%2d\n') <(cal)

Якщо вам не подобається мати вкладки як роздільники, просто додайте щось подібне sed 's/\t/ /'


Редагувати : спосіб простіше, не потрібно дбати про вкладки:

$ paste -d' ' <((echo -n '   '; ncal -w | tail -1 )| fold -w 3) <(cal)

Елегантний і втілює в собі багато 17 норм ESR від ESR . Повинно бути прийнятою відповіддю, оскільки вона справді поєднує результат calі ncal(інші підходи повторюють поведінку будь-якого calабо ncal).
єпископ

4

Один із способів використання Perl (моя вихідна мова calкоманди - іспанська, але, сподіваюся, результат не відрізняється від англійської):

$ cal | perl -pe 'if ( m/\A\s*\d/ ) { s/\A/++$i . qq[ ] x 2/e } else { s/\A/qq[ ] x 3/e }'

Вихід:

       enero de 2012   
   lu ma mi ju vi sá do
1                     1
2   2  3  4  5  6  7  8
3   9 10 11 12 13 14 15
4  16 17 18 19 20 21 22
5  23 24 25 26 27 28 29
6  30 31

Пояснення:

-pe                     # For every input line from previous pipe, execute  next
                        # instructions and print to output.
if ( m/\A\s*\d/ )       # If line begins with a digit omitting spaces...
s/\A/++$i . qq[ ] x 2/e # Insert at the beginning of the line a counter plus two spaces.
else                    # else...
s/\A/qq[ ] x 3/e        # Insert three spaces at the beginning of the line.

як це буде працювати протягом наступних місяців. Тижні лютого не починаються знову з 1, вони починаються з 5/6 аналогічно, березень буде з 9/10.
Нікхіл Маллі

кал 02 2012, це не вдасться ??
Nikhil Mulley

@Nikhil: Я не розумію, що ти маєш на увазі. Чи можете ви спробувати пояснити це більш глибоко? Чи не вдалося виконати сценарій cal 02 2012? Здавалося, це працює у моєму тесті.
Бірей

@Nikhil: Ага, добре. Я неправильно зрозумів питання. Це означає абсолютні числа тижнів, а не відносно кожного місяця. Через деякий час я видалю свою неправильну відповідь.
Бірей

1
класно .. не видаляйте відповідь, будь ласка, зберігайте її для довідки.
Нікхіл Мюллі

1

Не маючи достатнього представника, щоб прокоментувати відповідь SLM, gcal можна встановити на Mac OS за допомогою brew install gcal.

(Спершу я знайшов відповідь, потім ця відповідь на запитання була різною, але у відповіді unix бракувало всієї інформації, яка мені потрібна для встановлення на mac.)


0

Ось моє рішення, яке в коді коротше і працює чудово в інші дати, ніж у поточному місяці. Вибачте для американців, для цього використовується формат ISO, тобто перший день тижня - понеділок. Це робиться за допомогою параметра -m для cal та опції% V для дати

#!/bin/bash
if [ "$1" = "" ]
then
  when="now"
else
  when="$1"
fi
y=$(date --date "$when" +%Y )
if [ $? -ne 0 ]
then
  exit
fi
m=$(date --date "$when" +%m )
w=$(date --date $(printf %4d%02d01 $y $m) +%V)
cal -m $m $y |
  awk -v w=$w '
    NR>2{ww=w++}
    $0!=""{printf "%2s %s\n", ww , $0}
  '

0

Я зробив цей сценарій, щоб створити черговий календар для команд. Він генерує календар з номерами тижнів і присвоює їм імена (просто круглолітки). Після надрукування результату вам просто потрібно скопіювати його у Excel та зробити "текст у стовпець"; і ще раз виконайте "текст у стовпець" у першому стовпці, використовуючи опцію "фіксований". Перевага цього календаря (порівняння з горизонтальною орієнтацією) полягає в тому, що ви можете використовувати автоматичний фільтр (Alt + dff) і знаходити лише свої тижні.

#! / usr / bin / ksh
у = 2017 рік
набір-команда1 Петарс Юстас Річард Юкка Джеспер
набір-команда2 Модестас Тімо Матс Андреас

i1 = 0
i2 = 0
wn = 1
власний = 1

echo "WN Month Mo Tu We Th Fr Sa Su; Team1; Team2"
ycal = `для m в 1 2 3 4 5 6 7 8 9 10 11 12
робити
IFS =
        cal -m $ m $ y | egrep -v "Mo | ^ $" | під час читання рядка
        робити
                echo $ line | grep -q $ y && mname = $ line || друкувати $ mname $ line | sed 's /' $ y '//'
        зроблено
зроблено`
IFS =
відлуння "$ ycal" | під час читання line2
робити
IFS =
        echo "$ line2" | grep -v "1 2 3 4 5 6 7" | egrep -q "* 1 | * 1 $" || нехай wn ++
        [$ власні -не $ wn] && {\
                [$ i1 -eq $ {# team1 [@]} - 1] && i1 = 0 || нехай i1 ++; \
                [$ i2 -eq $ {# team2 [@]} - 1] && i2 = 0 || нехай i2 ++; }
        printf '% 2s% s;% s;% s \ n' $ wn $ line2 $ {team1 [$ i1]} $ {team2 [$ i2]}
        власний = $ wn
зроблено

Вибачте, код трохи неприємний ... і жодних коментарів ... але він працює добре;)


0

Мені не дуже хочеться встановлювати gcal, і я не міг змусити його працювати належним чином у своїй системі. Тож без гкалу відповідь фунолета справді найкраще рішення. Я просто змінив його крихітно, щоб він також зберігав форматування, наприклад, підсвічування дня , кольори тощо за допомогою команди. Я також видалив зайві символи, роблячи це придатним як псевдонім як такий:script

alias today="paste -d' ' <((echo ' '{,};ncal -w|tail -1)|fold -w3) <(script /dev/null -qc cal)"

Або замінити calновою функцією. Однак з цим ви не можете робити подібні речі cal -3. Ви отримуєте правильні тижні, але вони не вирівняні належним чином. Просте, але не повне рішення - перевірити, чи calвикликається без аргументів, наприклад:

function cal {
    if [[ $# -eq 0 ]]; then
        paste -d' ' <((echo ' '{,};ncal -w $@|tail -1)|fold -w3) <(script /dev/null -qc "cal $@")
    else
        /usr/bin/cal "$@"
    fi
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.