试图实现以下目标让我苦苦思索:
将Unix cal
输出转换为乳胶表代码,使用短而甜的单行(或几行)。
E.g 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]'
答案 0 :(得分:3)
在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
输出。
答案 1 :(得分:2)
使用awk
的GNU版本:
我使用英语cal
的{{1}}输出。
命令:
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";
}'
答案 2 :(得分:1)
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)]}'
答案 3 :(得分:0)
这可能对您有用:
cal | sed '1d;2{h;s/./ /g;x};/^\s*$/b;G;s/\n/ /;s/^...\(.\{15\}\).*/\1/;s/.../ &\t\&/g;s/\&$/\\\\/'
答案 4 :(得分:-1)
遵循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 & & & \\
答案 5 :(得分:-1)
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
替换为您希望的空格数
答案 6 :(得分:-1)
这适用于我cal
的实现,它使用四个字符的列,并有一个显示月份和年份的初始标题行
cal | perl -pe "next if $.==1;s/..../$&&/g;s/&$/\\\\/"
看起来您的列可能有8个字符,并且没有标题行,在这种情况下
cal | perl -pe "s/.{8}/$&&/g;s/&$/\\\\/"
应该做的伎俩,但要准备好调整它。