Преобразовать вывод `Cal` Unix в код латексной таблицы: однострочное решение? - PullRequest
5 голосов
/ 05 февраля 2012

Попытка добиться следующего заставила меня задуматься:

Конвертировать вывод Unix cal в код латексной таблицы, используя короткий и приятный однострочный (или многострочный).

Например, cal -h 02 2012 | $magicline должно дать

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

Единственное разумное решение, которое я мог найти до сих пор, было

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

... и я очень старался.Хорошая вещь о том, что это несложно и легко для понимания, плохая вещь о том, что он «негибкий» (он не может справиться с 8-недельной неделей) и немного многословно.Я ищу альтернативные решения, чтобы учиться; -)

РЕДАКТИРОВАТЬ: Нашел другое, которое кажется приемлемым

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

РЕДАКТИРОВАТЬ: Хороший:

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

Ответы [ 7 ]

3 голосов
/ 05 февраля 2012

Протестировано на 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;'

Где cal вывод имеет 3-символьные столбцы; {3} можно изменить в соответствии с cal выводом.

2 голосов
/ 05 февраля 2012

Использование версии GNU awk:

Мой вывод cal с использованием английского LANG.

Команда:

LANG=en_US cal

Выход:

    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

awk в одну строку:

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";
}'

Результат:

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 голос
/ 05 февраля 2012
cal 02 2012|perl -lnE'$.==1||eof||do{$,="\t&";$\="\t\\\\\n";$l=$_;print map{substr($l,$_*3,3)}(1..5)}'

мой новый фаворит:

cal 02 2012|perl -F'(.{1,3})' -anE'BEGIN{$,="\t&";$\="\t\\\\\n"}$.==1||eof||do{$i//=@F;print@F[map{$_*2-1}(1..$i/2)]}'
0 голосов
/ 05 февраля 2012

Это может работать для вас:

cal | sed '1d;2{h;s/./ /g;x};/^\s*$/b;G;s/\n/ /;s/^...\(.\{15\}\).*/\1/;s/.../ &\t\&/g;s/\&$/\\\\/' 
0 голосов
/ 05 февраля 2012

Это работает для моей реализации cal, которая использует четырехсимвольные столбцы и имеет начальную строку заголовка, показывающую месяц и год

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

Похоже, что у вас могут быть столбцы из восьми символов без строки заголовка, в этом случае

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

следует сделать трюк, но будьте готовы его подправить.

0 голосов
/ 05 февраля 2012
cal -h 02 2012| cut -c4-17 | sed -r 's/(..)\s/\0\t\&/g' | sed 's/$/\t\\\\/' | head -n-1 | tail -n +2

Это даст:

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

Вы можете легко заменить \t на желаемое количество пробелов

0 голосов
/ 05 февраля 2012

Должен работать лайкер awk 1:

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");
}'

ВЫВОД:

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   &   &   & \\
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...