Visualizzazione del numero della settimana in un determinato formato usando ncal o cal


16

Non ti piace solo quando due comandi fanno ciascuno una cosa che vuoi ma nessuno dei due fa?

Questo è ciò che calfa. Bella formattazione. Manca i numeri delle settimane però:

$ 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              

Questo è ciò che ncalfa. Strana formattazione, ma con numeri settimanali:

$ 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   

Il tipo di output che voglio, in realtà un incrocio tra cale 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

Risposte:


13

Se nessuno di questi comandi soddisfa le tue esigenze puoi usarlo gcal ciò che desideri.

Esempio

$ 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

Stampa il numero della settimana nell'ultima colonna a destra.

Riferimenti


gcal --starting-day=Monday --with-week-numbersoddisfa di più le mie esigenze, ma questo strumento è eccezionale.
k0pernikus,

9

Ciò evidenzia la data odierna e può essere visualizzato in qualsiasi mese tramite $1il modulo: YYYY-mm-dd... L'impostazione predefinita è la data odierna

È impostato per mostrare i numeri delle settimane ISO e il primo giorno della settimana è lunedì.

#!/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)

Ecco il display di questo mese (con 20evidenziato)

       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                

Non ho nemmeno notato l'iso-problema. Quello
succederà

1
@ k0pernikus: ho appena modificato lo script .. (circa 35 minuti dopo aver pubblicato il commento sopra) .. Stava per essere catturato 08e 09interpretato come ottale anziché decimale .. Ora dovrebbe andare bene ...
Peter.O,

7

Puoi usare nlper numerare le linee (questo è lo scopo del programma :). Ma devi estrarre la prima settimana del mese da qualche parte. Può essere fatto da ncalsolo:

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

Inseriamo questo come parametro nlnell'opzione -v(numero di riga iniziale) e lo diciamo solo a righe di numeri con numeri o spazi.

$ 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

Questo è terribilmente fragile però. Ad ogni modo, se non hai bisogno caldelle opzioni più avanzate, funzionerà. Puoi metterlo in un file e sostituirlo "$@"dove l'ho messo 2 2012.


EDIT: Ma questo è SBAGLIATO! Ho appena notato che la prima settimana di gennaio può avere il numero 52 o 53! Quindi non ci resta che fare un'eccezione per gennaio, oppure estrarre tutti i numeri delle settimane da ncale applicarli all'output di cal.

Questa è la soluzione che ho pensato inizialmente, ma ho pensato (erroneamente) che avrei semplificato usando nl. Usa paste, che unisce i file fianco a fianco. Poiché non esiste alcun file, dobbiamo usare il bashism<(...) ; questo è quello che stavo cercando di evitare.

Il nostro primo "file" sarà un elenco dei numeri delle settimane, con due righe vuote all'inizio:

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


52
 1
 2
 3
 4
 5

Il secondo, solo l'output di cal. Tutti insieme, come parametri per 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

Molto più disordinato e incompatibile dell'altro. En fin ...


Non così eccezionale: - /. Vedi la mia modifica.
angus,

7

Generare la sequenza di settimane con ncale utilizzare pasteper avere entrambe le uscite fianco a fianco.

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

Se non ti piace avere le schede come delimitatori, aggiungi qualcosa di simile sed 's/\t/ /'


Modifica : molto più semplice, non è necessario preoccuparsi delle schede:

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

Elegante e incarna molte delle 17 Regole Unix dell'ESR . Dovrebbe essere la risposta accettata in quanto combina veramente l'output di cale ncal(altri approcci replicano il comportamento di uno calo di due ncal).
vescovo,

4

Un modo usando Perl (la mia lingua di output del calcomando è lo spagnolo, ma spero che il risultato non vari dall'inglese):

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

Produzione:

       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

Spiegazione:

-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.

come funzionerà per i mesi successivi. Le settimane di febbraio non ricominciano di nuovo 1, ma iniziano dal 5/6 allo stesso modo Marzo sarà dal 9/10.
Nikhil Mulley,

cal 02 2012, avrà questo fallito ??
Nikhil Mulley,

@Nikhil: non capisco cosa intendi. Puoi provare a spiegarlo più in profondità? Lo script fallisce cal 02 2012? Sembrava funzionare nel mio test.
Birei,

@Nikhil: Ah, ok. Ho capito male la domanda. Significa numeri settimanali assoluti e non relativi a ciascun mese. Eliminerò la mia risposta sbagliata tra poco.
Birei,

1
cool..non cancellare la risposta, ti preghiamo di conservarla come riferimento.
Nikhil Mulley,

1

Senza abbastanza rappresentante per commentare la risposta di slm, gcal può essere installato su Mac OS usando brew install gcal.

(Ho trovato prima la risposta qui, quindi questa risposta su chiedere in modo diverso, ma la risposta unix mancava di tutte le informazioni necessarie per installare sul Mac.)


0

Ecco la mia soluzione che è più breve nel codice e funziona bene per altre date rispetto al mese corrente. Ci scusiamo per gli Stati Uniti, questo utilizza il formato ISO, ovvero il 1 ° giorno della settimana è lunedì. Questo viene fatto con l'opzione -m per cal e l'opzione% V per data

#!/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

Ho realizzato questo script per generare un calendario di turno per i team. Genera calendario con numeri settimanali e assegnando loro dei nomi (semplicemente round robin). Dopo aver stampato l'output, devi solo copiarlo in Excel e fare "text to column" di; e ancora una volta esegui "text to column" sulla prima colonna usando l'opzione "fixed". Il vantaggio di questo calendario (rispetto all'orientamento orizzontale) è che puoi usare il filtro automatico (Alt + dff) e trovare solo le tue settimane.

#! / Usr / bin / ksh
y = 2.017
set -A team1 Petars Justas Richard Jukka Jesper
set -A team2 Modestas Timo Mats Andreas

i1 = 0
i2 = 0
wn = 1
proprio = 1

echo "WN Mese Lu Ma Me Gi Ve Sa Do; Squadra1; Squadra2"
ycal = `per m in 1 2 3 4 5 6 7 8 9 10 11 12
fare
IFS =
        cal -m $ m $ y | egrep -v "Mo | ^ $" | mentre leggi la riga
        fare
                echo $ line | grep -q $ y && mname = $ line || stampa $ mname $ line | sed 's /' $ y '//'
        fatto
done`
IFS =
echo "$ ycal" | mentre leggi line2
fare
IFS =
        echo "$ line2" | grep -v "1 2 3 4 5 6 7" | egrep -q "* 1 | * 1 $" || lascia wn ++
        [$ own -ne $ wn] && {\
                [$ i1 -eq $ {# team1 [@]} - 1] && i1 = 0 || lascia che i1 ++; \
                [$ i2 -eq $ {# team2 [@]} - 1] && i2 = 0 || lascia che i2 ++; }
        printf '% 2s% s;% s;% s \ n' $ wn $ line2 $ {team1 [$ i1]} $ {team2 [$ i2]}
        possedere = $ wn
fatto

Spiacente, codice un po 'brutto ... e nessun commento ... ma funziona bene;)


0

Non voglio davvero installarlo gcale non riesco a farlo funzionare correttamente sul mio sistema. Quindi, senza gcal, la risposta di funollet è davvero la soluzione migliore. L'ho appena cambiato un po 'in modo da preservare anche la formattazione come evidenziazione del giorno , colori ecc. Usando il comando. Ho anche rimosso i caratteri ridondanti, rendendolo adatto come alias, in quanto tale:script

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

Oppure sostituisci calcon una nuova funzione. Tuttavia, con questo non puoi fare cose del genere cal -3. Ottieni le settimane corrette ma non sono allineate correttamente. Una soluzione semplice ma non completa è verificare se calviene chiamato senza argomenti, in questo modo:

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
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.