Exibindo o número da semana em determinado formato usando ncal ou cal

15

Você simplesmente não adora quando dois comandos cada um fazem uma coisa que você deseja, mas nem os dois?

Isto é o que calfaz. Boa formatação. Faltam números de semana:

$ 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              

Isto é o que ncalfaz. Formatação estranha, mas com números da semana:

$ 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   

O tipo de saída que eu quero, na verdade, um cruzamento entre 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
k0pernikus
fonte

Respostas:

13

Se nenhum desses comandos atender às suas necessidades, você poderá usar gcalo que deseja.

Exemplo

$ 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 o número da semana na última coluna à direita.

Referências

slm
fonte
gcal --starting-day=Monday --with-week-numberatende às minhas necessidades ainda mais, esta ferramenta é ótima.
Kdpernikus
9

Isso destaca a data de hoje e pode ser exibido em qualquer mês $1no formato: YYYY-mm-dd... O padrão é a data de hoje

Está configurado para mostrar os números ISO da semana, e o primeiro dia da semana é segunda-feira.

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

Aqui está a exibição deste mês (com 20destaque)

       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                
Peter.O
fonte
Eu nem percebi a questão iso. Isso vai fazer :)
k0pernikus
1
@ k0pernikus: Acabei de modificar o script .. (cerca de 35 minutos depois que você postou o comentário acima) .. Ele estava sendo capturado 08e 09interpretado como octal em vez de decimal .. Deve ficar bem agora ...
Pedro.O
7

Você pode usar nlpara numerar as linhas (esse é o objetivo do programa :). Mas você precisa extrair a primeira semana do mês de algum lugar. Isso pode ser feito por ncalsi só:

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

Nós inserimos isso como um parâmetro na nlopção -v(número da linha inicial) e dizemos para ele apenas numerar linhas com números ou espaços.

$ 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

Tudo isso é terrivelmente frágil. De qualquer forma, se você não precisar caldas opções mais avançadas, ele funcionará. Você pode colocá-lo em um arquivo e substituir "$@"onde eu coloco 2 2012.


EDIT: Mas isso está errado! Acabei de notar que a primeira semana de janeiro pode ter o número 52 ou 53! Portanto, basta abrir uma exceção para janeiro ou apenas extrair todos os números das semanas ncale aplicá-los à saída de cal.

Esta é a solução que pensei originalmente, mas pensei (erroneamente) que simplificaria usando nl. Ele usa paste, que mescla arquivos lado a lado. Como não há nenhum arquivo, temos que usar o basismo <(...); era isso que eu estava tentando evitar.

Nosso primeiro "arquivo" será uma lista dos números da semana, com duas linhas vazias no início:

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


52
 1
 2
 3
 4
 5

O segundo, apenas a saída de cal. Todos juntos, como parâmetros para 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

Muito mais bagunçado e incompatível que o outro. En fin ...

angus
fonte
Não é tão bom: - /. Veja minha edição.
angus
7

Gere a sequência de semanas com ncale use pastepara ter as duas saídas lado a lado.

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

Se você não gosta de ter guias como delimitadores, basta adicionar algo como sed 's/\t/ /'


Edit : muito mais simples, não há necessidade de se preocupar com as guias:

$ paste -d' ' <((echo -n '   '; ncal -w | tail -1 )| fold -w 3) <(cal)
funollet
fonte
Elegante e incorpora muitas das 17 regras do Unix da ESR . Deve ser a resposta aceita, pois combina verdadeiramente a saída de cale ncal(outras abordagens replicam o comportamento de um calou de ncal).
bispo
4

Uma maneira de usar Perl (meu idioma de saída do calcomando é o espanhol, mas espero que o resultado não varie do inglês):

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

Resultado:

       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

Explicação:

-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.
Birei
fonte
como isso funcionará nos meses subsequentes. As semanas de fevereiro não começam novamente 1, elas começam em 5/6 da mesma forma que março será em 9/10.
precisa saber é o seguinte
cal 02 2012, ele falhou ??
precisa saber é o seguinte
@ Nikhil: Eu não entendo o que você quer dizer. Você pode tentar explicar mais detalhadamente? O script falha cal 02 2012? Pareceu funcionar no meu teste.
Birei
@ Nikhil: Ah, ok. Não entendi bem a pergunta. Significa números absolutos da semana e não em relação a cada mês. Apagarei minha resposta errada daqui a pouco.
Birei
1
legal .. não apague a resposta, guarde-a para referência.
Nikhil Mulley
1

Sem representante suficiente para comentar a resposta do slm, o gcal pode ser instalado no Mac OS usando brew install gcal.

(Encontrei a resposta aqui primeiro, depois a resposta é diferente, mas a resposta para o unix não possuía todas as informações necessárias para instalar no mac.)

user3.1415927
fonte
0

Aqui está minha solução, que é mais curta em código e funciona bem em outras datas além do mês atual. Desculpe pelo povo dos EUA, isso usa o formato ISO, ou seja, o 1º dia da semana é segunda-feira. Isso é feito com a opção -m para cal e a opção% V para a 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}
  '
Gunstick
fonte
0

Eu fiz esse script para gerar um calendário de plantão para as equipes. Ele gera calendário com números da semana e atribui nomes a eles (simplesmente round-robin). Depois que a saída é impressa, você só precisa copiá-la para o Excel e fazer "texto para coluna" por; e, mais uma vez, execute "texto na coluna" na primeira coluna usando a opção "fixo". A vantagem deste calendário (comparando com a orientação horizontal) é que você pode usar o filtro automático (Alt + dff) e encontrar apenas as suas semanas.

#! / 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
own = 1

eco "WN Month Mo Tu We Th Fr Sa Su; Team1; Team2"
ycal = `para m em 1 2 3 4 5 6 7 8 9 10 11 12
Faz
IFS =
        cal -m $ m $ y | egrep -v "Mo | ^ $" | enquanto lê a linha
        Faz
                eco $ line | grep -q $ y && mname = $ line || print $ mname $ line | sed 's /' $ y '//'
        feito
feito`
IFS =
eco "$ ycal" | enquanto lê a linha2
Faz
IFS =
        eco "$ line2" | grep -v "1 2 3 4 5 6 7" | egrep -q "* 1 | * 1 $" || deixe wn ++
        [$ own -ne $ wn] && {\
                [$ i1-eq $ {# team1 [@]} - 1] && i1 = 0 || deixe i1 ++; \
                [$ i2-eq $ {# team2 [@]} - 1] && i2 = 0 || deixe i2 ++; }
        printf '% 2s% s;% s;% s \ n' $ wn $ line2 $ {team1 [$ i1]} $ {team2 [$ i2]}
        own = $ wn
feito

Desculpe, codifique um pouco desagradável ... e sem comentários ... mas funciona bem;)

Petras L
fonte
0

Eu realmente não quero instalar gcale não consegui fazê-lo funcionar corretamente no meu sistema. Portanto, sem o gcal, a resposta do funollet é realmente a melhor solução. Eu apenas mudei um pouquinho para preservar a formatação, como destaque do dia , cores etc. usando o comando Também removi caracteres redundantes, tornando-o adequado como um alias, como tal:script

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

Ou substitua calpor uma nova função. No entanto, com isso, você não pode fazer coisas como cal -3. Você recebe as semanas corretas, mas elas não estão alinhadas corretamente. Uma solução simples, mas não completa, é verificar se calé chamado sem argumentos, assim:

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
}
cinco
fonte