読者です 読者をやめる 読者になる 読者になる

clmemoの内容をメールに投げるシェルスクリプトを勝手に改造する

ここまでのあらすじ

id:yaotti さんが、clmemoの内容をメールに投げてくれるシェルスクリプトを作りました。でも、コードがちょっと汚くて不満があるようです。なので、僕が勝手に直すことにしました。

要するに何をすればいいの?

clmemo.elというEmacs-Lispでメモをじゃんじゃん書いていると、こんな感じのファイルができます。

2008-12-09  Hogehoge 

	* title: this line is item heading.
	item item item

2008-12-03  Hogehoge 

	* title: this line is item heading.
	item item item

以下続く ...

このうち最近7日分だけを取り出してメールで送りたい。作戦としては、8日目の行番号を求めて、その一つ上の行までを出力する、というやりかたでいきます。

ソースコード

#!/bin/bash

# この辺はいっしょ
clmemo="/path/to/your/clmemo/clmemo.txt" # clmemoへのパス
day=7 #何日分を送るか
address="hoge@example.com" #mail address
subject="clmemfo[weekly]" #subject

# ここからが本番
DATE_REGEX='[0-9]\{4\}-[0-9]\{1,2\}-[0-9]\{2\}'
line=$(sed -n "/$DATE_REGEX/=" $clmemo | sed -n $(expr $day + 1)p)
head -n $(expr $line - 1) $clmemo | mail -s $subject $address

ポイント

ポイントとなる所は以下の3つです。

  • ``ではなく$()を使う

bashにはコマンド置換という機能があって、`COMMAND`とバッククォートで囲った部分はコマンドが出力した標準出力の内容に置き換えられます。この``は伝統的なshのやりかたで、最近のbashでは代わりに$(COMMAND)がよく使われます(一応bashでも``は使えます)。機能としては``といっしょですが、$()の方が簡単に入れ子にできるので便利です。それにあわせて、さりげなく1行目を#!/bin/bashに代えておきました。

  • sedの=コマンドを使う

sedには'='という、行番号だけを出力するコマンドがあります。なので、初めのsedコマンドは「$DATE_REGEXにマッチした行の行番号を出力する」という意味になります。これで、一旦grep -nで出力した後うにゃうにゃする、という処理がいらなくなります。

  • メール本文を|でつないでmailコマンドに渡す

mailコマンドは標準入力をメール本文として送信します。なので、ヒアドキュメントを使わなくても素直にメール内容を|(パイプ)でつなげばOKです。

最後に

これでちゃんと動くと思います。ちなみに、ここまで書いといてなんですが、僕はemacsを使っていません。