2012-02-05 2 views
5

Cercando di raggiungere i seguenti lottato mia mente:Converti output `cal` Unix in codice tabella latex: soluzione one-liner?

Convert Unix cal uscita in codice tavolo lattice, utilizzando un breve e dolce one-liner (o pochi-liner).

es cal -h 02 2012 | $magicline dovrebbe produrre

Mo  &Tu  &We  &Th  &Fr  \\ 
     &  & 1  & 2  & 3  \\ 
6  & 7  & 8  & 9  &10  \\ 
13  &14  &15  &16  &17  \\ 
20  &21  &22  &23  &24  \\ 
27  &28  &  &  &  \\ 

L'unica soluzione ragionevole ho potuto venire in mente finora era

cal -h | sed -r -e '1d' -e \ 
    's/^(..)?(...)?(...)?(...)?(...)?(...)?(...)?$/\2\t\&\3\t\&\4\t\&\5\t\&\6\t\\\\/' 

... e ho davvero provato duramente. La cosa bella è che è semplice e facile da capire, la cosa brutta è che è "non flessibile" (non poteva sopportare una settimana di 8 giorni) e un po 'prolisso. Sto cercando soluzioni alternative per imparare da ;-)

EDIT: Trovato un altro che sembra accettabile

cal -h | tail -n +2 | 
    perl -ne 'chomp; 
     $,="\t&"; 
     $\="\t\\\\\n"; 
     $line=$_; 
     print map {substr($line,$_*3,3)} (1..5)' 

EDIT: Nice one:

cal -h | perl \ 
    -F'(.{1,3})' -ane \ 
     'BEGIN{$,="\t&";$\="\t\\\\\n"} 
      next if $.==1; 
      print @F[3,5,7,9,11]' 
+2

Codice golf ha il proprio SE forum. – tripleee

+1

Quale versione di 'cal' su quale piattaforma accetta l'opzione' -h'? –

+0

@ Jonathan: la [versione di Ubuntu di cal] (http://manpages.ubuntu.com/manpages/gutsy/man1/cal.1.html) sembra essere l'unica. – Borodin

risposta

2

Utilizzando la versione GNU di awk:

La mia uscita di cal utilizzando un inglese LANG.

Comando:

LANG=en_US cal 

uscita:

February 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 

Il awk di una sola riga:

LANG=en_US cal | awk ' 
BEGIN { 
    FIELDWIDTHS = "3 3 3 3 3 3 3"; 
    OFS = "&"; 
} 
FNR == 1 || $0 ~ /^\s*$/ { next } 
{ 
    for (i=2; i<=6; i++) { 
    printf "%-3s%2s", $i, i < 6 ? OFS : "\\\\"; 
    } 
    printf "\n"; 
}' 

Risultato:

Mo &Tu &We &Th &Fr \\ 
    & & 1 & 2 & 3 \\ 
6 & 7 & 8 & 9 &10 \\ 
13 &14 &15 &16 &17 \\ 
20 &21 &22 &23 &24 \\ 
27 &28 &29 & & \\ 
+1

buon approccio, grazie per il bit 'FIELDWIDTHS'. Che ne dite di 'cal | awk 'BEGIN {FIELDWIDTHS = "3 3 3 3 3 3 3"; OFS = "\ t &"; ORS = "\ t \\\\\ n";} FNR! = 1 {stampa $ 2, $ 3, $ 4, $ 5, $ 6;} ''? –

-1

seguito awk 1 liner dovrebbe funzionare:

cal 02 2012 | awk 'NR>1 && NF>0 { 
    if (NR==2) 
     col=NF; 
    j=1; 
    if (NR==3 && NF<col) { 
     if (NF<col) 
     printf(" & "); 
     for(j=2; j<=col-NF; j++) 
     printf(" &"); 
    } 
    for (i=j; i<=col; i++) { 
     if (j==1 && i==j) 
     printf("%2s ", $(i-j+1)); 
     else 
     printf(" %3s", "&" $(i-j+1)); 
    } 
    printf(" \\\\\n"); 
}' 
.210

USCITA:

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 & & & \\ 
+0

Sfortunatamente no. 1 febbraio 2012 è un mercoledì, non una domenica! –

+0

Pls controlla la risposta modificata ora. – anubhava

-1
cal -h 02 2012| cut -c4-17 | sed -r 's/(..)\s/\0\t\&/g' | sed 's/$/\t\\\\/' | head -n-1 | tail -n +2 

Questo produrrà:

Mo  &Tu  &We  &Th  &Fr \\ 
     &  & 1  & 2  & 3 \\ 
6  & 7  & 8  & 9  &10 \\ 
13  &14  &15  &16  &17 \\ 
20  &21  &22  &23  &24 \\ 
27  &28  &29  &  &  \\ 

Si può facilmente sostituire \t con numero di spazi che si desidera

+0

No, non lo fa (non crea celle dopo '29') ... –

+0

@JoSo, beh, lo fa se usi 4 spazi invece di' \ t' come ho incollato qui l'output. –

-1

Questo funziona per la mia realizzazione di cal, che utilizza colonne di quattro caratteri e ha una riga del titolo iniziale che mostra il mese e l'anno

cal | perl -pe "next if $.==1;s/..../$&&/g;s/&$/\\\\/" 

Sembra come se la tua può avere colonne di otto caratteri e non ha alcuna riga del titolo, nel qual caso

cal | perl -pe "s/.{8}/$&&/g;s/&$/\\\\/" 

dovrebbe fare il trucco, ma essere pronti a modificarlo.

+0

Sfortunatamente, non creare una cella vuota per i giorni che sono già nel mese successivo ... Anche se l'espansione di una linea all'inizio potrebbe risolverla. Grazie per l'opzione '-p'. –

3

provata su OS-X:

cal 02 2012 |grep . |tail +2 |perl -F'/(.{3})/' -ane \ 
    'chomp(@F=grep $_,@F); $m=$#F if !$m; printf "%s"."\t&%s"x$m."\t\\\\\n", @F;' 

Dove cal uscita ha colonne 3 caratteri; {3} potrebbe essere modificato per corrispondere all'uscita cal.

+0

+1 Non capisco una parola, tempo per imparare la nuova magia di Perl ;-) –

+0

Penso 'cal -h | perl -F '(. {1,3})' -ane 'BEGIN {$, = "\ t &"; $ \ = "\ t \\\\\ n"} next se $. == 1; print @F [3,5,7,9,11] ''è molto preciso e" solido ". Domanda aggiornata –

1
cal 02 2012|perl -lnE'$.==1||eof||do{$,="\t&";$\="\t\\\\\n";$l=$_;print map{substr($l,$_*3,3)}(1..5)}' 

il mio nuovo preferito:

cal 02 2012|perl -F'(.{1,3})' -anE'BEGIN{$,="\t&";$\="\t\\\\\n"}$.==1||eof||do{$i//[email protected];[email protected][map{$_*2-1}(1..$i/2)]}' 
+0

Questa è LA risposta (anche se solo una versione più breve della mia; -]) –

+0

Sì, è una modifica della tua versione. –

0

Questo potrebbe funzionare per voi:

cal | sed '1d;2{h;s/./ /g;x};/^\s*$/b;G;s/\n/ /;s/^...\(.\{15\}\).*/\1/;s/.../ &\t\&/g;s/\&$/\\\\/' 
+0

perché il voto negativo? Non vedo nulla di sbagliato in questo. –

+1

@JohnRiselvato grazie. – potong