2012年3月28日

ひらがな・カタカナ変換

ひらがなをカタカナに、カタカナをひらがなにそれぞれ変換するperlスクリプト。
これをOS Xのサービスに入れておくと便利かも。

ひらがな→カタカナ
use utf8;
binmode STDOUT, ':utf8'; 
binmode STDERR, ':utf8'; 
binmode STDIN, ':utf8';
while (<>) {
 tr/ぁ-ゖ/ァ-ヶ/;
 s/わ゙/ヷ/;
 s/ゐ゙/ヸ/;
 s/ゑ゙/ヹ/;
 s/を゙/ヺ/;
 tr/ゝゞ/ヽヾ/;
 s/ゟ/ヨリ/;
 print $_;
}

カタカナ→ひらがな
use utf8;
binmode STDOUT, ':utf8'; 
binmode STDERR, ':utf8'; 
binmode STDIN, ':utf8';
while (<>) {
 tr/ァ-ヶ/ぁ-ゖ/;
 s/ヷ/わ゙/;
 s/ヸ/ゐ゙/;
 s/ヹ/ゑ゙/;
 s/ヺ/を゙/;
 tr/ヽヾ/ゝゞ/;
 s/ヿ/こと/;
 print $_;
}



「わ゙ゐ゙ゑ゙を゙」で、trコマンドじゃなくて、sコマンドを使ってるのは、合成用濁点を使っているからです。濁点付きの「わゐゑを」という文字はありませんもん。

なお、小書きの「ヵ」「ヶ」を「ゕ」「ゖ」に変換するのは間違っていると思うけど、ここでは形式的に変換してみました。「ヵ」「ヶ」は「箇」や「个」の略字・異体であって、仮名ではないはず。


 NOTA BENE :  当初「use encoding "utf8";」という指定をしてましたが、これは使うべきではないとのことです(→『404 Blog Not Found』「perl - use encoding; #は黒歴史」)。


2012年3月24日

たくさんのファイルをいっぺんにリネーム

きのうの隔週勉強会で「リネームソフトってWindows用ばっかりや」という声が(一部から)聞こえたけど*、Mac OS Xだと別段必要もないんじゃないかな。Windowsはシェルがしょぼいから、ファイルのリネーム程度のことでもソフトを作らなあかんということですよ。実際にはMac用のもたくさんあるようです。私がWindowsのこともMacのことも知らないだけでした^^)

OS Xはunixですから。


勉強会で出て来たのは、「感-5864.ai」という形式の名前を持つファイルを、冒頭の漢字1文字とハイフンまでを外した「5864.ai」という形式の名前にリネームしたい。たくさんあるのを一括処理したいという課題でした。

Terminal(shellはbash)でやれば簡単。
bashの「for name [ in word ] ; do list ; done」構文を使います。

sedでやってみる

まず、考えたのは手に馴染んでいるsedを使うやりかた。
for i in *.ai
> do
> cp $i `basename $i | gsed -e 's/^.-//'`
> done
  1. basenameコマンドでファイル名をテキストとして取得:basename $i
  2. それをパイプを通じてsedに渡し、
  3. 先頭の一文字とそれに続くハイフン(^.-)を削除:s/^.-//
  4. ここまでの実行結果(`basename $i | gsed -e 's/^.-//'`)を新しいファイル名としてcpコマンドに渡す
という手順。

ただし、漢字など多バイト文字はOS X付属のsedではうまく変換できないので、GNU sedが必要です。(bashの環境変数のうちLANGも、LANG=ja_JP.UTF-8とする必要があります)

perlをつかう

そこで、OS X付属のperlを使ってみました。こんな感じです。
for i in *.ai
> do
> cp $i `basename $i | perl -CIO -pe 'use utf8; s/^.-//;'`
> done

】当初、perl -pe 'use utf8; s/^.+-//;'」と書いていて、どうして「+」が必要なんだろうと不思議に思っていたのですが、エンコーディングの指定書式を旧式の「use encoding "utf8"」にすると文字数が思惑どおりになりました。しかし、その後、perlの起動オプション「-C」で出入力のエンコーディングを指定することを教わりました(man perlrun参照)。これでやっと現代的なコードになりました。みなさん、ありがとうございます。


bashだけでできる

そうこうしているうちに、bashだけでできるのに気付きました。こうです。
for i in *.ai
> do
> cp $i ${i/*-/}
> done

変数を展開する際にその一部を書き換える機能をbash自体が持っているんです。
bashのmanpageでは、「Parameter Expansion」項の最後の方に載ってます。
 ${parameter/pattern/string}という構文です。
(今回はpatternの文字列を削除するのでstring文字列は

検索パターンの書き方にちょっと癖があるし、機能もsedやperlほどではないのですが、今回のような事例ならこれで充分役立ちます。

2012年3月5日

どこでもunixフィルタ

おとといの記事のつづきです。


OS Xの「サービス」に「シェルスクリプトを実行」を組み込む時、オプションの「ワークフローの実行時にこのアクションを表示」をONにしておけば、その時々でスクリプトを書き換えられるので便利。


環境変数の設定だけしておけば汎用フィルタとなります。
export LANG=ja_JP.UTF-8
これを「汎用篩」という名前で保存しておきます。

では、facebookの投稿欄で使ってみましょう(ブラウザはSafariです)。


無理矢理の例ですが、各教科ごとの平均点を計算させてみます。計算する行を選択して、上で作ったサービス「汎用篩」を呼び出します。


生徒 A  B  C  平均
国語 85 89 84
算数 92 90 88
理科 78 75 80
社会 94 90 92

おとといの例とは違って、「シェルスクリプトを実行」windowが現れます。
ここにスクリプトを書きこみます。

今回はawkスクリプトを書いてみましょう。awkはOS Xネイティブのものでもutf-8テキストをちゃんと扱えます。

awk '{total=$2+$3+$4; avg=total/3; print $0, avg}'


えい!


生徒 A  B  C  平均
国語 85 89 84 86
算数 92 90 88 90
理科 78 75 80 77.6667
社会 94 90 92 92

できました^^

2012年3月3日

InDesign上のテキストをperlやsedで編集

(2016-1-11注記: CS6ぐらいから仕様が変わったのか、InDesignからサービスにテキストを渡せなくなっています。残念 orz)

Macはテキスト処理も強力なのです。なにせunix系ですから。
しかも、Terminalじゃなくても、Webページの入力フォーム内や、もちろんInDesignのフレームグリッド内でもperlやsed、awkを使ったテキスト編集ができてしまうのです。

もう、これだけでもWindowsを捨てて、Macにしなさいと声を大にして言えます。

InDesignだとこんな具合;
洋数字を漢数字に:置換前
置換後
このあと、「六八〇」→「六百八十」と単位語を書き加えたりしなければなりませんが、手間や書き換え間違いはずいぶん減ります。



これは、OS Xの「サービス」という名前のサービスを使っているのです。
「サービス」は選択部分に対して適用されます。(選択部分が何なのかによってサービスメニューの内容が変ります)


「サービス」はOS X付属のAutomator.appで作ります。
Otto君が手にしているのは他ならぬ「パイプ」です。









起動したら「新規作成」ダイアログで「サービス」を選びます。












左側にある「アクション」を右側の編集欄にドラッグして、unixのフィルタをパイプで繫いでいくように、並べていきます。

↑これは「サービス」ではなく「フォルダアクション」の例です
今回作るフィルタで使う「シェルスクリプトを実行」は「アクション」の「ユーティリティ」の中にあります。それを編集欄にドラッグすると…
ここで、「選択されたテキストを出力で置き換える」にチェックを入れるのがミソです(デフォルトではOFFになってます)。

unix流にいうと選択部分を標準入力・標準出力として扱っているのです。
なお、流れるテキストストリームは、文字コード:utf-8、改行:LF (とおもいきや、InDesignのようにCR改行のテキストを渡すものもあるようです)。



シェルには各種のshellが選べます。perl、python、pubyを直接呼び出すこともできます。








それぞれ、あらかじめ、標準入出力用の枠組みが用意されています。perlだとこんな具合。










あとは、やらせたいフィルタスクリプトをここに書いて、適当な名前をつけて保存すれば、メニューバーのアプリケーションメニューやマウス右クリックでのコンテキストメニューでの「サービス」から呼び出せるようになります。

(この段階では特定のスクリプトを書かず、「汎用のフィルタ」とするのも便利です。詳しくは後日の「どこでもunixフィルタ」記事をどうぞ)


なお、自作の「サービス」は、各ユーザの「~/Library/Services/」フォルダに保存されるのですが、Lionからこのフォルダが不可視とされてしまいました。Finderのメニューバーの「移動」をOptionキーを押しながらクリックすると「ライブラリ」に移動できますが、Automatorの「開く」ダイアログには「移動」がないので、Finderのサイドバーにドラッグして登録しておくことをお薦めします。


実例:

洋数字を漢数字に書き換えるサービスならこんな具合です。shellとしてperlを使ってます。

use encoding 'utf-8';
while (<>) {
 y/0-9/0-9/;
 y/,./,./;
 y/0123456789/〇一二三四五六七八九/;
 y/,./千・/;
 print $_;
}
「use encoding 'utf-8'」と宣言してやれば、仮名漢字スクリプトもOKです。

メールなど改行で体裁を作ってしまったテキストの行を連結させるサービスでは、bashからsedを呼び出しています。

export LANG=ja_JP.UTF-8
tr \\r \\n | /usr/local/bin/sed -f /Users/mt/bin/jointline.sed
「export LANG=ja_JP.UTF-8」で環境変数LANGをutf-8用にするのが肝心。

なお、OS Xネイティブのsedはutf-8をまだうまく扱えないので、GNU Sedを使う必要があります。GNU Sedはソースから、configure→make→make install で簡単にインストールできます。
また、InDesignのようにCR改行テキストを渡すものもあるので、「tr \\r \\n」で改行をLFに揃えます。

この例で呼び出している jointline.sed は2010年6月に書いた「行連結sedスクリプト」です。
:loop
$!N
s/\(.\+\)\n\([^ ]\+\)/\1\2/
t loop
P
D
 は全角空白です。


*改題しました。2012-03-04