将 Unix `cal` 输出转换为乳胶表代码:单行解决方案?

发布于 2025-01-02 19:32:57 字数 1207 浏览 0 评论 0原文

试图实现以下目标让我很挣扎:

使用简短而甜蜜的单行(或几行)将 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]'

Trying to achieve the following struggled my mind:

Convert Unix cal output to latex table code, using a short and sweet one-liner (or few-liner).

E.g cal -h 02 2012 | $magicline should yield

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

The only reasonable solution I could come up with so far was

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

... and I really tried hard. The nice thing about it being that it's uncomplicated and easy to understand, the bad thing about it that it's "unflexible" (It couldn't cope with a week of 8 days) and a little verbose. I'm looking for alternative solutions to learn from ;-)

EDIT: Found another one that seems acceptable

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]'

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

命比纸薄 2025-01-09 19:32:57

在 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 输出。

Tested on 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;'

Where cal output has 3-character columns; {3} could be changed to match your cal output.

﹂绝世的画 2025-01-09 19:32:57

使用 GNU 版本的 awk

我使用英语 LANG 输出的 cal

命令:

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

Using the GNU version of awk:

My output of cal using an english LANG.

Command:

LANG=en_US cal

Output:

    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

The awk one-line:

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

Result:

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  &    &   \\
空城缀染半城烟沙 2025-01-09 19:32:57
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)]}'
cal 02 2012|perl -lnE'$.==1||eof||do{$,="\t&";$\="\t\\\\\n";$l=$_;print map{substr($l,$_*3,3)}(1..5)}'

my new favorite:

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)]}'
以往的大感动 2025-01-09 19:32:57

这可能对你有用:

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

This might work for you:

cal | sed '1d;2{h;s/./ /g;x};/^\s*$/b;G;s/\n/ /;s/^...\(.\{15\}\).*/\1/;s/.../ &\t\&/g;s/\&$/\\\\/' 
请持续率性 2025-01-09 19:32:57

这适用于我的 cal 实现,它使用四个字符的列,并有一个显示月份和年份的初始标题行

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

看起来好像你的可能有八个字符的列并且没有标题行,在哪种情况

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

应该可以解决问题,但要做好调整的准备。

This works for my implementation of cal, which uses four-character columns and has an initial title line showing the month and year

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

It looks as though yours may have eight-character columns and has no title line, in which case

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

should do the trick, but be prepared to tweak it.

音盲 2025-01-09 19:32:57
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 替换为您想要的空格数

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

This will produce:

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

You can easily replace \t with number of spaces you wish

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文