2つのコマンドがそれぞれ1つの必要なことを実行し、両方のコマンドが両方を実行するときに、単にそれが好きではないですか?
これはcal
が行うことです。素敵なフォーマット。ただし、週数が足りません:
$ 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
これはncal
が行うことです。奇妙なフォーマットですが、週番号があります:
$ 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
必要な出力の種類、実際にはcal
と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
これらのコマンドのどちらもニーズに合わない場合は、gcal
を使用して代わりにやりたいことができます。
$ 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
右側の最後の列に週番号を出力します。
これは今日の日付を強調表示し、$1
を介して任意の月を次の形式で表示できます:YYYY-mm-dd
...デフォルトは今日の日付です
ISO週番号を表示するように設定されており、最初の平日は月曜日です。
#!/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)
これが今月の表示です(20
が強調表示されています)
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
nl
を使用して行に番号を付けることができます(それがプログラムの目的です:)。しかし、月の最初の週をどこかから抽出する必要があります。 ncal
自体から実行できます。
_$ ncal -w 2 2012 | tail -1 | awk '{print $1}'
5
_
これをパラメータとしてnl
のオプション_-v
_(開始行番号)に挿入し、番号またはスペースを含む行番号のみを指定します。
_$ 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
_
しかし、これはすべてひどく壊れやすいものです。とにかく、cal
のより高度なオプションが必要ない場合は、機能します。あなたはそれをファイルに入れて、_"$@"
_を入れて、_2 2012
_を入れます。
編集:しかし、これは間違っています! 1月の最初の週が52または53になる可能性があることに気づきました!したがって、1月を例外にするか、_allncal
から週番号を抽出して、cal
の出力に適用する必要があります。
これは私が最初に考えた解決策ですが、私は(誤って)nl
を使用してそれを簡略化すると思いました。ファイルを並べてマージするpaste
を使用します。ファイルがないため、bashism <(...)
を使用する必要があります。それは私が避けようとしていたことです。
最初の「ファイル」は週番号のリストで、最初に2行の空行があります。
_$ printf ' \n \n' && printf '%2d \n' $(ncal -w 1 2011 | tail -1)
52
1
2
3
4
5
_
2つ目は、cal
の出力だけです。すべてをまとめて、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
_
はるかに厄介で互換性がありません。 En fin ...
ncal
を使用して週のシーケンスを生成し、paste
を使用して両方の出力を並べて表示します。
$ paste <(echo; echo; ncal -w | tail -1 | xargs -n1 printf '%2d\n') <(cal)
区切り文字としてタブを使用したくない場合は、sed 's/\t/ /'
編集:タブを気にする必要がなく、非常に簡単です。
$ paste -d' ' <((echo -n ' '; ncal -w | tail -1 )| fold -w 3) <(cal)
Perlを使用する1つの方法(cal
コマンドの出力言語はスペイン語ですが、結果が英語と変わらないことを願っています):
$ cal | Perl -pe 'if ( m/\A\s*\d/ ) { s/\A/++$i . qq[ ] x 2/e } else { s/\A/qq[ ] x 3/e }'
出力:
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
説明:
-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.
gcal
を実際にインストールしたくないので、自分のシステムで正しく動作させることができませんでした。したがって、gcalなしでは、funolletの答えが実際に最良の解決策です。 dayなどのフォーマットも保持するように、少し変更しましたscript
コマンドを使用して、強調表示、colorsなど。また、次のように、冗長な文字を削除して、エイリアスとして適切にしました。
alias today="paste -d' ' <((echo ' '{,};ncal -w|tail -1)|fold -w3) <(script /dev/null -qc cal)"
または、cal
を新しい関数に置き換えます。ただし、これではcal -3
のようなことはできません。あなたは正しい週を取得しますが、それらは正しく整列されていません。単純ですが完全ではない解決策は、次のように、引数なしでcal
が呼び出されているかどうかを確認することです。
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
}
このスクリプトを実行して、チームの当番カレンダーを生成しました。それは週番号とそれらに名前を割り当てる(単にラウンドロビン)カレンダーを生成します。出力が印刷された後、それをExcelにコピーして、「テキストから列へ」を実行するだけです。そしてもう一度、「固定」オプションを使用して、最初の列で「テキストから列へ」を実行します。このカレンダーの利点(水平方向と比較して)は、オートフィルター(Alt + d f f)を使用して週のみを検索できることです。
#!/ 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 echo "WN Month Mo Tu We Th Th Fr Sa Su; Team1; Team2 " ycal =` for m in 1 2 3 4 5 6 7 8 9 10 11 12 do IFS = cal -m $ m $ y | egrep -v "Mo | ^ $" | while read line do echo $ line | grep -q $ y && mname = $ line || print $ mname $ line | sed 's /' $ y '//' done done` IFS = echo "$ ycal" |読みながらline2 do IFS = echo "$ line2" | grep -v "1 2 3 4 5 6 7" | egrep -q "* 1 | * 1 $" | | let wn ++ [$ own -ne $ wn] && {\ [$ i1 -eq $ {#team1 [@]}-1] && i1 = 0 || let i1 ++;\ [$ i2 -eq $ {#team2 [@]}-1] && i2 = 0 || i2 ++をしましょう; } printf '%2s%s;%s;%s\n' $ wn $ line2 $ {team1 [$ i1]} $ {team2 [$ i2]} own = $ wn 完了
申し訳ありませんが、コードは少し厄介です...そしてコメントはありません...しかしそれはうまくいきます;)
コードが短く、今月以外の日付でも問題なく機能する私の解決策を次に示します。米国の人には申し訳ありませんが、これはISO形式を使用しています。つまり、週の最初の日が月曜日です。これは、calの-mオプションとdateの%Vオプションで行われます
#!/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}
'