Affichage du numéro de semaine dans un certain format en utilisant ncal ou cal


16

Ne l'aimez-vous pas simplement quand deux commandes font chacune une chose que vous voulez, mais pas les deux non plus?

C'est ce qui calfait. Joli formatage. Il manque cependant des numéros de semaine:

$ 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              

C'est ce qui ncalfait. Formatage étrange, mais avec des numéros de semaine:

$ 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   

Le type de sortie que je veux, en fait un croisement entre calet 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

Réponses:


13

Si aucune de ces commandes ne répond à vos besoins, vous pouvez utiliser gcalà la place ce que vous voulez.

Exemple

$ 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

Imprime le numéro de la semaine dans la dernière colonne à droite.

Les références


gcal --starting-day=Monday --with-week-numbercorrespond plus à mes besoins mais cet outil est génial.
k0pernikus

9

Cela met en évidence la date du jour et peut afficher n'importe quel mois via $1sous la forme: YYYY-mm-dd... Il s'agit par défaut de la date du jour

Il est configuré pour afficher les numéros de semaine ISO et le premier jour de la semaine étant le lundi.

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

Voici l'affichage de ce mois-ci (avec 20surligné)

       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                

Je n'ai même pas remarqué le problème iso. Cela fera l'affaire :)
k0pernikus

1
@ k0pernikus: Je viens de modifier le script .. (environ 35 minutes après avoir posté le commentaire ci-dessus) .. Il se rattrapait 08et 09était interprété comme octal au lieu de décimal .. Ça devrait aller maintenant ...
Peter.O

7

Vous pouvez utiliser nlpour numéroter les lignes (c'est le but du programme :). Mais vous devez extraire la première semaine du mois de quelque part. Cela peut se faire de ncallui-même:

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

Nous l'insérons en tant que paramètre de nll'option -v(numéro de ligne de départ), et nous le disons uniquement aux lignes de numéro avec des nombres ou des espaces.

$ 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

Mais tout cela est terriblement fragile. Quoi qu'il en soit, si vous n'avez pas besoin caldes options plus avancées, cela fonctionnera. Vous pouvez le mettre dans un fichier et remplacer "$@"où je l'ai mis 2 2012.


EDIT: Mais c'est faux! Je viens de remarquer que la première semaine de janvier peut avoir le numéro 52 ou 53! Nous devons donc soit faire une exception pour janvier, soit extraire tous les numéros de semaine de ncalet les appliquer à la sortie de cal.

C'est la solution que je pensais à l'origine, mais j'ai pensé (à tort) que je la simplifierais en utilisant nl. Il utilise paste, qui fusionne les fichiers côte à côte. Puisqu'il n'y a pas de fichier, nous devons utiliser le bashisme <(...); c'est ce que j'essayais d'éviter.

Notre premier "fichier" sera une liste des numéros de semaine, avec deux lignes vides au début:

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


52
 1
 2
 3
 4
 5

Le second, juste la sortie de cal. Tous ensemble, comme paramètrespaste :

$ 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

Beaucoup plus désordonné et incompatible que l'autre. En fin ...


Pas si bien :-/. Voir mon montage.
angus

7

Générez la séquence des semaines avec ncalet utilisez pastepour avoir les deux sorties côte à côte.

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

Si vous n'aimez pas avoir des onglets comme délimiteurs, ajoutez simplement quelque chose comme sed 's/\t/ /'


Edit : beaucoup plus simple, pas besoin de se soucier des onglets:

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

Élégant et incarne la plupart des 17 règles Unix d' ESR . Doit être la réponse acceptée car elle combine vraiment la sortie de calet ncal(d'autres approches reproduisent le comportement de l'un calou de l'autre ncal).
évêque

4

Une façon d'utiliser Perl (ma langue de sortie de la calcommande est l'espagnol, mais j'espère que le résultat ne varie pas de l'anglais):

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

Production:

       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

Explication:

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

comment cela fonctionnera-t-il pour les mois suivants? Les semaines de février ne recommencent pas 1, elles commencent à partir du 5/6 de même mars sera du 9/10.
Nikhil Mulley

cal 02 2012, aura-t-il échoué ??
Nikhil Mulley

@ Nikhil: Je ne comprends pas ce que tu veux dire. Pouvez-vous essayer de l'expliquer plus en profondeur? Le script échoue- cal 02 2012t-il? Cela semblait fonctionner dans mon test.
Birei

@Nikhil: Ah, d'accord. J'ai mal compris la question. Cela signifie des numéros de semaine absolus et non relatifs à chaque mois. Je supprimerai ma mauvaise réponse dans un moment.
Birei

1
cool .. ne supprimez pas la réponse, veuillez la conserver pour référence.
Nikhil Mulley

1

Sans suffisamment de représentants pour commenter la réponse de slm, gcal peut être installé sur Mac OS en utilisant brew install gcal.

(J'ai trouvé la réponse ici d'abord, puis cette réponse sur demander différente, mais la réponse unix manquait toutes les informations dont j'avais besoin pour installer sur le mac.)


0

Voici ma solution qui est plus courte dans le code et fonctionne bien pour d'autres dates que le mois en cours. Désolé pour le peuple américain, cela utilise le format ISO, c'est-à-dire que le 1er jour de la semaine est lundi. Cela se fait avec l'option -m pour cal et l'option% V pour date

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

J'ai fait ce script pour générer un calendrier de garde pour les équipes. Il génère un calendrier avec des numéros de semaine et leur attribue des noms (simplement un round-robin). Une fois la sortie imprimée, il vous suffit de la copier pour exceller et de faire du "texte dans la colonne" par; et encore une fois, effectuez "text to column" sur la première colonne en utilisant l'option "fixed". L'avantage de ce calendrier (par rapport à l'orientation horizontale) est que vous pouvez utiliser un filtre automatique (Alt + dff) et ne trouver que vos semaines.

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

i1 = 0
i2 = 0
wn = 1
propre = 1

echo "WN Month Mo Tu We Th Fr Sa Su; Team1; Team2"
ycal = `pour m dans 1 2 3 4 5 6 7 8 9 10 11 12
faire
IFS =
        cal -m $ m $ y | egrep -v "Mo | ^ $" | en ligne de lecture
        faire
                echo $ line | grep -q $ y && mname = $ line || print $ mname $ line | sed 's /' $ y '//'
        terminé
fait »
IFS =
echo "$ ycal" | en lisant line2
faire
IFS =
        echo "$ line2" | grep -v "1 2 3 4 5 6 7" | egrep -q "* 1 | * 1 $" || laissez wn ++
        [$ own -ne $ wn] && {\
                [$ i1 -eq $ {# team1 [@]} - 1] && i1 = 0 || laissez i1 ++; \
                [$ i2 -eq $ {# team2 [@]} - 1] && i2 = 0 || laissez i2 ++; }
        printf '% 2s% s;% s;% s \ n' $ wn $ line2 $ {team1 [$ i1]} $ {team2 [$ i2]}
        propre = $ wn
terminé

Désolé, code un peu méchant ... et pas de commentaires ... mais ça marche bien;)


0

Je ne veux pas vraiment installer gcal, et je n'ai pas pu le faire fonctionner correctement sur mon système. Donc sans gcal, la réponse de funollet est en effet la meilleure solution. Je l'ai juste changé un tout petit peu pour qu'il préserve également la mise en forme comme le surlignage du jour , les couleurs, etc. en utilisant la commande. J'ai également supprimé les caractères redondants, le rendant approprié comme alias, en tant que tel:script

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

Ou remplacez-la calpar une nouvelle fonction. Cependant, avec cela, vous ne pouvez pas faire des choses comme cal -3. Vous obtenez les bonnes semaines mais elles ne sont pas alignées correctement. Une solution simple mais pas complète consiste à vérifier si calest appelé sans arguments, comme ceci:

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
}
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.