Greple 仕様変更と多色化
関連
--cut やめて --need にしました
新しく --need
というオプションを作って、マッチするパターンの数を指定できるようにしました。
そこで負の値を指定すると、今までの --cut
と同じ意味になります。
--cut
の方はわかりにくいので、まだ使っている人はいないだろうと思って削除しちゃいました。
ネガティブマッチを許す --allow
の方はそのままで、やはり負の値を受け付けるようにしました。
greple --need=2 --allow=1 'foo bar baz -yabba -dabba -doo'
--print 関数の仕様変更
--print
オプションで指定する関数の仕様を変えました。
今までは関数の返り値は見ていなかったのですが、今は返って来た値を出力するようになっています。 ですから、関数では出力したい文字列を返すようにします。 関数内で出力しちゃった場合には、空文字列を返してください。
また、--continue
オプションを指定すると、返り値をそのまま出力せずに、通常の出力処理を続けるようになっています。
元の文字列を変更してしまうと、うまく出ないことがあるので注意して使いましょう。
多色化
--colormode
で複数の色を指定できるようにしました。
そうすると、指定したキーワード毎に違う色を使うようになります。
また --colorful
というオプションを追加して、これは --colormode 'RD GD BD CD MD YD'
と同じ意味です。
このように出力されます。
こんな例だとあまり役に立つようには見えませんが、たとえばこんな風にするといくらか使い道はあるかもしれません。
greple --colorful --need 1 --icode=auto -e '\p{Han}+' -e '\p{InHiragana}+' -e '\p{InKatakana}+' -e '[a-zA-Z]+' -e '\d+' -e '[\pP\pS]+'
調子にのって --random
というオプションも付けてみました。
ポップな感じですが、あまり意味はありません。
greple --all --colorful --random '\S+' greple
Greple で iCal データを検索する
追記: 申し訳ありませんが、
--chdir, --glob オプション
OS X のカレンダーコマンドは iCalendar という形式でデータを管理していて、ファイルは ~/Library/Calendars というディレクトリの下に保存されている。
たとえば、こんな風にすれば iCal のデータを検索することはできる。
% cd ~/Library/Calendars
% grep PATTERN *.caldav/*.calendar/Events/*.ics
Greple の --chdir
と --glob
オプションを使うと、同じことがこんな風にできる。
% greple --chdir ~/Library/Calendars --glob='*.caldav/*.calendar/Events/*.ics' PATTERN
複数のディレクトリを --chdir
で指定することもできる。
その場合、それぞれのディレクトリに移動した後で --glob
オプションを解釈する。
% greple --chdir '~/Library/Calendars/*.caldav/*.calendar/Events/' --glob '*.ics' PATTERN
憶えておくのは大変なので、alias を作ってもいいし、~/.greplerc
ファイルに次のように書いておくと --ical_data
という新しいオプションが有効になる。
% greple --ical_data PATTERN
これだと、マッチした行しか表示されないので日付とかがわからない。
iCal のデータは、1つのイベントを1つのファイルに保存しているので、ファイル全体を表示させるためには、--all
というオプションを使う。
% greple --ical_data --all PATTERN
ここまでは grep
の -r
オプションを使っても、大体同じことができる。
マニュアルには書いてないが、
と思ったけど、-C
オプションに -1
を指定するとファイル全体を表示するようだ。-C
オプションに負の数を指定した場合の挙動は不可解だ。
% grep -rhC-1 --include '*.ics' PATTERN *.caldav
--print オプション
greple の --print
オプションを使うと、出力用の関数を定義することができる。
もっとも簡単な使い方はこんな具合。
% greple --print='sub{$_}' PATTERN
値には Perl のサブルーチン名を指定するか、直接コーディングする。
マッチした領域は $_
変数に入ってきて、関数の返り値が出力される。
iCal のデータを表示するためには、たとえば ~/.greplerc
にこのような関数を定義する。
.greplrc definition to search iCal data and displa ...
こうして、次のように実行すると、iCal のデータを1行ずつ表示してくれる。 イベント名だけを検索したければ SUMMARY 行を指定する。 TODO などを除外して EVENT だけを検索したければ、VEVENT というフィールドも指定する。
% greple --ical PATTERN
% greple --ical '^SUMMARY.*PATTERN'
% greple --ical 'VEVENT ^SUMMARY.*PATTERN'
これだと、順番が出鱈目なので、日付順に表示したければ結果を sort する。
--of
オプションで出力フィルタを指定することができるので、.greplerc
の中に --of=sort
を入れてしまっても構わない。
試しに、10年前の正月にどんな映画を観ていたかを検索してみるとこんな結果になった。
なるほど、とっとこハム太郎を観ていたのかw
% greple --ical '200401\d\d 映画' | sort
2003/01/02 14:00-15:00 映画:とっとこハム太郎 ハムハムハムージャ!幻のプリンセス
2003/01/02 15:00-16:30 映画:ゴジラ対メカゴジラ
2004/01/02 12:20-13:25 映画:劇場版 とっとこハム太郎ハムハムグランプリオーロラ谷の奇跡リボンちゃん危機一髪
2004/01/02 13:30-15:00 映画:ゴジラ×モスラ×メカゴジラ 東京SOS
2004/01/08 19:30-21:30 映画:ミシェル・ヴァイヨン@池袋HUMAX
2004/01/13 20:10-22:00 映画:ブルース・オールマイティ@サンシャイン
2004/01/16 20:40-22:55 映画:半落ち@サンシャイン
2004/01/21 22:00-00:00 映画:リクルート
2004/01/24 21:30-23:30 映画:タイムライン
2004/01/25 21:00-23:00 映画:首都消失@TV
2004/01/29 20:30-23:00 映画:ミスティック・リバー@新宿ジョイシネマ
おや、2003年のデータが混じってるな?と思ったら、こうやって中身を見ることができる。
% greple --ical_data --all ハムハムハムージャ!
すると、DTSTAMP というフィールドが2004年になっていることがわかった。 RFC2445 によれば、これはオブジェクトが作成された日付ということだ。
厳密に書くとすればこんな具合だろうか。 最初からきっちり書くのではなく、ゆるく初めて必要に応じて絞り込むような使い方がお勧めである。
% greple --ical '^BEGIN:VEVENT ^DTSTART.*200401\d\d ^SUMMARY.*映画' | sort
greple --strict オプション
先日の変更で、greple コマンドに --strict
オプションが付いている。実際には、デフォルトの挙動を変更して、以前と同じ動作をさせるために strict モードを追加したことになる。
何がどう変わったか。greple には --inside
, --outside
, --block
などのマッチする領域を制限するオプションがあるが、以前は指定したパターンが完全にこれらの領域に含まれている時だけマッチが成功した。現在は、パターンの一部でも領域に含まれていればマッチが成功するようになっている。
たとえば、
greple --inside and command
というパターンは、以前は決してマッチしなかったが、今はする。--outside
にしても結果は同じだ。
これが役に立つケースというのをあまり思いつかないのではあるが、たとえば
greple -n --block='(.*\n){1,10}' -e 'Be aware' README.md
みたいに、10行ずつのブロックを検索した時に、パターンが複数ブロックにまたがっている場合でも発見することができる。 以前は、1つのマッチは1つのブロックにしか影響を与えることができなかったのだが、それが複数ブロックになったということだ。
固定長のレコードデータなんかは、隣のレコードと一緒になってマッチしては困るだろうから --strict
オプションを使った方がいいだろう
greple --strict --block='(?s).{80}' ...
ハカイシをハックする
いろいろあって、墓石のデザインを考えることになった。経緯はすっとばして、結論として辿り着いたテーマは黄金比とスーパー楕円。黄金比は説明するまでもないだろう。ダビンチとかオウムガイのあれだ。と一言で片付けようと思ったが、え、オウムガイは違うのか?深入りすると長くなりそうなので保留。
楕円の公式は (x/n)2 + (y/m)2 = 1 だが、この2乗の部分が 2 より大きくなったものをスーパー楕円と呼ぶ。
Wolfram Alpha というサイトで、横 1.0 縦 1.6 の黄金比の3乗のスーパー楕円を描くとこのようになる。
必要なのは第一象限だけなので、そこの部分を何種類か表示してどれがいいかを考える。冪数は整数ではなくてもよい。
2.5 か 2.8 のどちらがいいか迷って、最終的には 2.8 を選択した。
業者さんに渡すための図形を描くのには gnuplot を使用。 方程式を解いて
y = 1.6 (1 - x 2.8) 1/2.8
を求めればいい。 第一象限だけを表示するプログラムはこんなものか。 初めて使ったので稚拙な部分があると思うがご勘弁を。
Golden Ratio Superellipse by Gnuplot
デザインには Google Sketchup を使用。曲線を描くのに Ruby のプラグインを使おうかとも思ったが、プラグインも Ruby も未経験で時間がかかりそうだったので見送り。Perl で計算した座標を手作業で入力した。x を 0 から 1.0 まで変化させて求めるわけだが、1.0 に近くなるに従って細かくしないと線が荒くなってしまう。その辺は適当に調整したのだが、後から考えると角度を等分して cosign を求めた方がよかった。5度間隔で表示するとすれば、こんな具合になるだろう。今回は幅300mm、高さ480mmの楕円を描くので300倍している。
x=0.000000, 0.000000, 480.000000
x=0.087156, 26.146723, 479.815046
x=0.173648, 52.094453, 478.722973
x=0.258819, 77.645714, 476.076512
x=0.342020, 102.606043, 471.360546
x=0.422618, 126.785479, 464.161505
x=0.500000, 150.000000, 454.150177
x=0.573576, 172.072931, 441.067116
x=0.642788, 192.836283, 424.708888
x=0.707107, 212.132034, 404.914265
x=0.766044, 229.813333, 381.549201
x=0.819152, 245.745613, 354.488587
x=0.866025, 259.807621, 323.591140
x=0.906308, 271.892336, 288.659917
x=0.939693, 281.907786, 249.371266
x=0.965926, 289.777748, 205.125829
x=0.984808, 295.442326, 154.665394
x=0.996195, 298.858409, 94.680866
x=1.000000, 300.000000, 0.000000
結果として、このようなものができあがった。細かい部分は石材屋さんが細工するので、この通りに仕上がるわけではない。花立や香炉の穴の部分もスーパー楕円だ。石塔の部分が奥行き1尺、高さ1尺6寸の黄金比。幅は2尺ということだったが、頑張って2尺5寸とってくれることになったので、正面もほぼ黄金比で出来上がることになった。石材屋さんとしてはもう少し高くしたいらしいが、せっかくなのでこのままで行くことに。
テクスチャを貼るともっとそれらしいのだが、モノがモノだけになんか生々しいのでワイヤーフレームです。さて、どうなりますでしょうか。
greple command released
先月 mg というコマンドを Unicode 対応しましたが、その後全面的に見直してオプション体系も新しくなったので、greple という名前に変更してリリースすることにしました。
ドキュメントを git に合わせて markdown で書いたら、それは hatenablog でしか使えないようなので、ついでにブログも移行してみた。
使用例は今後も更新するので、最新版はこちらをどうぞ。
Greple Examples
Keywords / キーワード
find multiple words all / 全部ある行を表示する
greple 'foo bar baz'
greple -e foo -e bar -e baz
x foo baz
o foo bar baz
o baz, bar and foo
negative match / 除外したい単語を指定する
greple 'foo bar baz -yabba -dabba -doo'
greple -e foo -e bar -e baz -v yabba -v dabba -v doo
x foo bar
o baz bar foo
x foo bar baz doo
alternative match / どれかひとつあればいいんだけど
greple 'foo bar baz ?yabba ?dabba ?doo'
greple 'foo bar baz yabba|dabba|doo'
greple -e foo -e bar -e baz -e 'yabba|dabba|doo'
greple '?foo|bar ?yabba|dabba' # foo|bar|yabba|dabba
greple 'foo|bar yabba|dabba' # you want this? こーいうこと?
cut down the match count / マッチに必要な数をまける
greple --cut=1 'foo bar baz'
o foo bar baz
o foo baz
o bar baz
x foo
allow negative match / ネガティブマッチを許す
greple --allow=1 'foo -bar -baz'
o foo bar
o foo baz
x foo bar baz
narrow down the match result / 検索結果を絞り込む
greple pattern *.html
greple pattern *.html -v foo
greple pattern *.html -v foo -v bar
greple pattern *.html -v foo -v bar -v baz
# isn't this nice?
# これ、結構、よくないすか?
Areas / 領域
find and
not in command
/ command
に含まれない and
を探す
greple --outside=command and
find from C comment / C のコメント部分を検索
greple --inside='(?s)\/\*.*?\*\/'
find from shell comment / シェルのコメントを検索する
greple --inside='#.*'
find variablish things from lines start with my
/ my
ではじまる行から変数ぽいものを探す
greple --inside='^\s*my\b.*' '[\$\@]\w+'
Blocks / ブロック
paragraph mode / パラグラフモード
greple -p 'foo bar baz'
# show preveous and next paragraph together
# 前後のパラグラフも表示する
greple -pC1 'foo bar baz' …
show paragraph not including pattern / 何かが含まれないパラグラフを表示する
greple --nocolor --re '(.+\n)+' -v '(?i)pattern'
show lines not including pattern / 何かが含まれない行を表示する
use grep -v !
show pages including pattern / ページ単位で表示する
greple -n --block='(.*\n){1,66}' pattern
show entire file / ファイル全体を表示する
greple --block='(?s).*'
show all comment blocks / コメントブロックを全部表示する
greple -o --nocolor --re '\/\*(?s:.*?)\*\/' /usr/include/stdio.h
Text / テキスト
複数行から検索する
greple 'リゾート|ステーション'
will match this text:
こんなのもみつけてくれます。
というか、日本語を処理する場合、そうでないと使い物にならないでしょ。
長い駅名を探すと「東京ディズニーランド・ステーション駅」「リ
ゾートゲートウェイ・ステーション駅」「東京ディズニーシー・ス
テーション駅」「南阿蘇水の生まれる里白水高原駅」などが…
list up all Japanese Katakana words / 片仮名の単語を全部抜き出す
greple -ho --nocolor --join '\p{utf8::InKatakana}[\n\p{utf8::InKatakana}]*'
you like it? / 気に入ったらこんな風にどうぞ
cat >> ~/.greplerc
define :kana: \p{utf8::InKatakana}
option --kanalist --color=never --only-matching --join --re ':kana:[:kana:\n]+'
find cyclic redundancy c*
greple -pi -e 'cyclic redundancy c\w+' rfc*
greple -o --joinby=' ' -ie 'cyclic redundancy c\w+' rfc*
find Kanji and not CJKUnifiedIdeographs / 漢字だけど CJKUnifiedIdeographs じゃない文字を探す
greple --inside='\p{Han}+' '[^\s\p{InCJKUnifiedIdeographs}]'
# This works, but quite slow. Not recommended.
# 動くけどチョー遅いからこんなことしちゃ駄目よ。
guess data encoding / 文字コードを自動判定する
greple --icode=guess
specify data encoding / 文字コードを指定する
greple --icode=euc-jp
greple --icode=shif-jis
specify guessing code set / 自動判定するコードを指定する
greple --icode=utf8,euc-jp,shift-jis,7bit-jis
add to guessing code set / 自動判定するコードを追加する
greple --icode=+euc-kr
Filter / フィルター
find from EXIF data / EXIF 情報を検索する
greple --if='env LC_ALL=en_US exif -x /dev/stdin' 'Image_Description|Manufacturer' *.jpg
MBPrintf の Github ページを作ってみた
Github Pages というのがあることを発見したので作ってみました。こんなカッコいいページが簡単に作れちゃうんですね。内容は大したことないんですが :-)。独自ドメインも使えるみたいだけど、それはまたそのうち。
中身は、2年前に作った MBPrintf.pm という Perl モジュールのページですよ。マルチバイト文字を扱うための printf です。
EUC の場合は、何も考えずに printf で日本語を処理しても、大概の場合は期待通りに出るんですね。20年も使っている自前の住所録コマンドをやっと Unicode 対応にしたら、printf の表示が出鱈目になっちゃって、昔のコードを読み直して修正するのが面倒だったので、まんま printf を置き換えられるようにしたものです。やっつけですが、とりあえず何も考えずに置き換えれば動くので結構便利です。効率はいいとは言えないけど、変に考えてフォーマット文字列を作るとか、頑張って printf を使わずに出力するとかよりはマシかもしれません。
試してないけど、韓国語や中国語でも使えるんじゃないのかなあ。
そうそう、マニュアルに書き忘れていますが、mbwidth という関数を export すると表示幅がわかります。
ファイルハンドルも含めて、完全に printf と互換にできる方法を知っている人がいたら教えてください。
NAME MBPrintf − printf family functions to handle multi−byte characters SYNOPSIS use MBPrintf; mbprintf(FORMAT, LIST) mbsprintf(FORMAT, LIST) DESCRIPTION "MBPrintf" is a almost‐printf‐compatible library with a capability of handling multi‐byte wide characters properly. "MBPrintf" は、マルチバイト文字を処理するための、ほぼ printf と互換 のライブラリ関数です。 FUNCTIONS mbprintf(FORMAT, LIST) mbsprintf(FORMAT, LIST) Use just like Perl’s printf and sprintf functions except that printf does not take FILEHANDLE as a first argument. 使い方は Perl の printf, sprintf と同じです。ただし、ファイルハン ドルを指定することはできません。 IMPLEMENTATION NOTES Strings in the LIST which contains wide‐width character are replaced before formatting, and recovered after the process. Number of replaced arguments are limited by 25. LIST 中に全角文字を含む文字列があった場合、整形処理を行う前に別の文字列に 置換され、処理が終わった後で元に戻されます。変換する文字列の最大数は25に 制限されています。 Unique replacement string contains a combination of control characters (Control‐A to Control‐E). So, if the FORMAT contains a string in this range, it has a chance to be a subject of replacement. 置換文字列には制御文字 (コントロールAからコントロールE)が含まれるため、 これらの文字が FORMAT に含まれている場合には注意が必要です。 Wide‐character judgement is done based on Unicode property East_Asian_Width is Wide or FullWidth. There is another value Ambiguous and treatment of this type characters are literaly ambiguous and is not considered now. It might be better to use Unicode::EastAsianWidth instead. 全角文字の判定は Unicode の East_Asian_Width プロパティが Wide あるいは FullWidth であることで行っています。これ以外に Ambiguous という値があり ますが、取り扱いが文字通り曖昧なため考慮していません。 Unicode::EastAsianWidth を使った方がいいのかも知れません。 AUTHOR Copyright (c) 2011 Kazumasa Utashiro. All rights reserved. LICENSE See <http://www.perl.com/perl/misc/Artistic.html>
はてなの Facebook 連携も初体験。
Unicode 対応 mg
昔から使っている mg という文字列検索コマンドを2年ぶりに更新しました。
今回の変更点は以下の通り。
- ファイルのデフォルト文字コードを utf8 にした。
ファイルのコード指定には -j オプションを使用する。コードの自動判定を行う場合には -j Guess を指定する。
もしかすると、今まで Unicode 対応したことをアナウンスしていなかったかもしれません。基本的な機能は大きく変わっていませんが、Unicode 対応したことで検索文字列の指定にはかなり柔軟性が出てきたはずです。
Unicode 対応は、まだ実験的なコードとして実装されているため、他の機能と整合がとれていないこともあります。マニュアルの対応も完全ではないので注意してください。
2年前に書きかけた記事があったので、暇ができたら更新して公開します。
2013.10.23 追記:
オプションに -j を使うのはやめて、--icode と --ocode というオプションを作りました。
ファイルコードを指定 | --icode=euc-jp |
指定したコードから自動判定 | --icode=euc-jp,jis |
(区切りはスペースでもいい) | --icode="euc-jp jis" |
(複数指定してもいい) | --icode=euc-jp --icode=jis |
デフォルトのコードから自動判定 | --icode=guess |
デフォルトのコードに追加して自動判定 | --icode=+euc-kr |
当たり前かも知れませんが、Unicode に対応したことで日本語以外のテキストにも使えるようになりました。ちょっと感動です。
2013.10.24 追記:
バイナリファイルを検索する -B オプションと、テキストファイルだけを検索する -T オプションは、Unicode 対応機能と整合性が悪いため廃止しました。