web-dev-qa-db-ja.com

calを使用して当日を出力

calコマンドを使用して当日を出力するように求められます。

これまでのところ、現在の日付の前に_シンボル。ここでgrepを使用することにしました:cal | grep '\b_*'、しかしそれは全体の週を出力します。私はいくつかの変種を試しましたが、うまくいきませんでした。

実際、当日の数字が一桁しかない場合もあるので、使わざるを得ないようですtr -d ' ' ここに。

これらすべてのコマンドを組み合わせる方法がわかりません。

7
Welez

calコマンドの出力が端末ではない場合、今日の日番号に下線を適用します。これは、下線を引く各文字の前にアンダースコアとバックスペース文字を置くことで構成されます。文字を視覚的に表示するとわかります(^Hcontrol-H 、つまりバックスペース文字です):

cal | cat -A
cal | cat -vet

または、16進ダンプを確認します。

cal | hd
cal | od -t x1

したがって、必要なのは、下線付きの文字を検出して出力することです。

GNU grepを使用すると、正規表現のすべての一致を印刷する簡単な方法があります。-oオプションを使用します。下線文字は、拡張正規表現_^H.と一致します。^Hは、文字列のバックスペース文字です。 、2文字の^Hではなく、.が印刷する文字です。バックスペース文字を入力する代わりに、これがcalが出力でアンダースコアを使用する唯一の方法であるという事実に頼ることができます。アンダースコアを検出し、バックスペースを一致しない文字として残すのに十分です。

cal | grep -o '_..'

終了しましたが、出力にはアンダースコアとバックスラッシュのシーケンスが含まれており、数字は別々の行にあります。数字以外の文字をすべて削除できます(そして末尾の改行を追加し直します)。

cal | grep -o '_..' | tr -d 0-9; echo

または、パターン_..を繰り返して、複数の下線付きの数字を照合することもできます。これにより、出力に下線が残ります。trまたはsedを使用してそれを取り除くことができます。

cal | grep -E -o '(_..)*'
cal | grep -E -o '(_..)*' | tr -d '\b_'
cal | grep -E -o '(_..)*' | sed 's/_.//g'

これはsedで実行できますが、完全に簡単ではありません。 Sedは、一致する行のみを印刷する簡単な方法を提供します(-nオプションを使用して、明示的に印刷される行のみを取得します)が、1つの行に一致する複数のオカレンスを直接印刷する方法はありません。これを解決する方法は、最大2つの下線付き文字があるという事実を利用して、1つの下線付き文字を含む行を変換および出力する1つのsコマンドと、2つの行がある別の行を使用することです。前述のように、バックスペースを明示的に一致させません。

cal | sed -n 's/.*_.\(.\)_.\(.\).*/\1\2/p; s/.*_.\(.\).*/\1/p'

行に下線付きのセグメントが1つしかない場合、sedを使用する別のアプローチは、その前と後のすべてを削除することです。

cal | sed -n 's/^[^_]*_/_/; s/\(_..\)[^_]*$/\1/p'

これはアンダースコアを残します。 3回目の交換でそれらを削除できます。

cal | sed -n 's/^[^_]*_/_/; s/\(_..\)[^_]*$/\1/; s/_.//gp'

これを行う適切な方法は、dateを使用することです。

% date +%d
19

表示されるアンダースコアはアンダースコアではなく、端末によって表示される制御文字です。 本当にcalを使用したい場合は、その制御文字が何であるかを調べ、それを探す必要があります。これは、cal | xxdなどを使用して使用できます。

もう1つの問題は、calはstdoutがttyの場合にのみこの制御文字を出力するため、それが1つであることを納得させる必要があることです(これについてはscriptを検討してください)。

11
Chris Down

私は現在GNU calコマンドの前にいませんが、これはあなたが望むものに近いです:

cal | grep -Eo '_[[:digit:]]+' | sed 's/_//'

Grep -Eは、拡張正規表現を許可することを示しています([[:digit:]]クラスの場合)。 -oフラグは、一致する部分のみを出力するように指示します。 sedコマンドはアンダースコアを削除します。

それがcal + grepの方法ですが、 Chrisが言った のように、現在の日付を取得する通常の方法はdateコマンドを使用することです。

3
Jeff Schaller