一般公開「ターミナルの向こうから:海上 忍(連載終了)」
(MOSADeN Onlineでは、掲載日から180日を経過した記事を一般公開しています。)- 古典に学ぶ:sed(2)(2009/11/30:掲載)
- 古典に学ぶ:sed(1)(2009/11/24:掲載)
- 第57回 MOSA Software Meeting 2009 補遺(2009/10/28:掲載)
- 第56回 Appleが発信するオープンソースソフトウェア(2009/10/16:掲載)
- 第55回 Snow Leopardの変更点(2)(2009/09/16:掲載)
- 第54回 Snow Leopardの変更点(1)(2009/09/01:掲載)
-
古典に学ぶ:sed(2)
この記事は、2009年11月30日に掲載されました。 - Mac OS Xに収録のsedに関する問題
sedの説明を再開する前に、Mac OS Xに収録のsedに関する問題点を指摘しておきます。それは「改行文字の扱いが不適切」という問題です。開発元のFreeBSDプロジェクトも事態を認識しており、「man sed」を実行してオンラインマニュアルを表示すると、末尾にバグに関する記載があります。
値 0x5C (ASCII '¥') のバイトを含むマルチバイト文字は、 "a", "c",
"i" コマンドへの引数では、誤って行継続文字として扱われてしまうかもしれ
ません。マルチバイト文字は、 "s" と "y" コマンドでの区切り文字として
使用できません。
この問題はLeopard以前から指摘されていましたが、Snow Leopardの現在でも修正されていません。そのため、sコマンドを使い改行コードを含む文字列を置換する場合、改行コードが普通の文字列として処理されてしまうため、期待どおりに改行されないという事態が発生します。たとえば、以下のようなテキストファイル(test.txt)があるとします。
MOSA
Mac
iPhone
この2行目の部分(Mac)を「Macintosh(改行)Macintosh」に置換し、changed.txtというファイルに書き出すために、次のコマンドを実行してみます。意図通り処理されれば、全4行のうち2〜3行目が「Macintosh」になるはずですが……ASCII文字のみで構成されるファイルにおいても、改行コードの処理が適切に行われないことがわかると思います。
$ sed -e 's/Mac/Macintosh¥r¥nMacintosh/' test.txt > changed.txt
$ cat changed.txt
MOSA
MacintoshrnMacintosh
iPhone
対策ですが、GNU版sedを導入することが近道です。以下のコマンドラインをターミナルで順に実行すれば、/usr/local/bin/sedとしてGNU sed 4.2がインストールされます。「which sed」を実行したときの戻り値が「/usr/local/bin/sed」であれば、以降GNU版sedをデフォルトのsedとして利用できるようになります。
$ curl -O http://ring.riken.jp/archives/GNU/sed/sed-4.2.tar.gz
$ tar xzf sed-4.2.tar.gz
$ cd sed-4.2
$ ./configure --with-libiconv-prefix=/usr --with-libintl-prefix=/usr
$ make
$ sudo make install
sedが役立つ場面の1つが「特定のパターンを置換/除去する」ことです。正規表現でパターンを指定し、対象のテキストファイル上にある一致箇所を処理するというsedの使い方は、いわば基本中の基本です。ここでは、あるHTMLファイル(before.html)を対象に、sedでHTMLタグすべてを取り除いたうえで別のファイル(after.html)に書き出す、という処理を例に説明してみましょう。
$ cat before.html | sed 's/]*>//g' > after.html
パターンを記述するうえでの約束事を整理してみましょう。これを正規表現に落とし込んだものが上のコマンド実行例というわけです。
- HTMLタグ(「<」で始まり「>」で終わる)を対象とする。
- 「<」と「>」の間には、任意の長さの文字列が入る。
- 一致したパターンは削除する。
- ファイル上のすべての行を対象とする。
1ですが、「<」と「 >」の間に任意の長さを意味するメタキャラクタを挿入すればよさそうです。ここで使うのは、直前の1文字の0回以上の繰り返しを意味する「*」、すなわち「<*>」を仮の回答としておきます。
しかし、これでは直前の1文字が「<」となってしまい、タグを正しく検出できません。つまり、「>」の直前の1文字をどのように表現するか、という問題を解決しなければなりません。
ここで利用するのが、任意の1文字に一致しないキャラクタを意味する正規表現の「[^]」です。HTMLの場合、「>」がタグの終わりを意味しますから、「>」以外のキャラクタすべて、すなわち「[^>]」とすれば、「>」を除くキャラクタすべてを対象にできる、というわけです。
3ですが、置換を行う内部コマンド「s」の基本形、「s/before/after/」を使います。1と2をこれに当てはめると、beforeが「<[^>]*>」、afterはヌルキャラクタですから、「s/<[^>]*>//」ということになります。4は、前回紹介したとおり、すべての行を対象とする内部コマンド「g」を使います。これで、正解の「s/<[^>]*>//g」に辿り着くことができました。
いざコマンドを実行、期待どおりHTMLタグを取り除け……なかったことと思います。実は、この記述例では2行にまたがるパターンがマッチしないため、取りこぼしが多数発生してしまうのです。この対策については、また次回説明します。
古典に学ぶ:sed(1)
ある処理を実現したいとき、アプリケーションを開発することはその解決策の1つです。しかし、現在あるものをうまく使いこなせばその目的を達成できるとしたら……それで済ますに越したことはないかもしれません。今回は、「敢えてつくらず古典的なツールの組み合わせで解決する」ことをテーマに、UNIXコマンドのsedを利用したテキスト処理について解説します。
「Stream EDitor」を命名の由来とするsedは、文字データの整形処理を目的としたコマンドです。その歴史は古く、初出は1973年頃のAT&Tベル研究所とされていますから、UNIXの草創期からあるコマンドといえます。ちなみに、カリフォルニア大学バークレイ校でBill Joy氏らによりBSD UNIXの開発が始まったのが1974年、NEXTSTEP(v0.9)が初めて世に出たのが1988年ですから、斯業界においてはシーラカンス的な存在と言えないこともないでしょう。
しかし、その機能はいまなお古びることがありません。理由を挙げるとすれば、
- GUIを利用せず逐次ユーザに問い合わせることもない、非対話型のエディタである
- 対象が文字データ(プレインテキスト)である
- 文字データをファイルまたは標準入力(STDIN)経由で入力し、ファイルまたは標準出力(STDOUT)で出力することができる
- 正規表現を利用した文字列の検索/置換が可能
といったところでしょうか。エディタという文字面にとらわれると、TextEdit.appのようなスクリーンエディタを連想しがちですが、sedは検索/置換用コマンドのほうがイメージとしては近いといえます。プレインテキストという普遍的なデータを、GUIのように陳腐化する要素を持たずに処理するため、登場から35年以上経過した現在も第一線のコマンドであり続けるのでしょう。
そのsedの使い方ですが、論より証拠、有益と思われる処理を実際に試すことが理解の近道です。まずはターミナルを起動し、以下のコマンドラインを実行してください。
- – - – -
$ echo ‘xxmosaxxmosa’ | sed ‘s/mosa/MOSA/’
xxMOSAxxmosa
- – - – -
これがsedのもっともオーソドックスな利用法で、内部コマンド「s」を利用した文字列の置換です。書き方は「s/変換前/変換後/」、実行する場合には範囲をシングルクオートで囲むんだ「’s/変換前/変換後/’」が基本パターンです。ここでは、文字列「mosa」を大文字の「MOSA」に置換することで、echoコマンドが標準出力にアウトプットした「xxmosaxxmosa」を「xxMOSAxxmosa」に変換しています。行頭から検索を開始して最初に一致した部分のみを置換しているため、2回目に登場した「mosa」が置換されていないところがポイントです。
一致するすべての文字列を変換する場合には、置換のパターンを示した文字列の末尾に「g」を加えます。すなわち、行全体を検索して一致する語句すべてを置換する場合には、「’s/変換前/変換後/g’」と記述すればいいことになります。
- – - – -
$ echo ‘xxmosaxxmosa’ | sed ‘s/mosa/MOSA/g’
xxMOSAxxMOSA
- – - – -
どうですか? 「xxMOSAxxmosa」となっていた戻り値が「xxMOSAxxMOSA」に変化しているはずです。
sedの特徴として、冒頭に正規表現が利用できることを挙げました。上記の基本パターンを一歩進め、正規表現を使った文字列置換を行ってみましょう。最初の例は、括弧内に含まれる1文字に一致するパターンを指定する「[]」の使い方です。アルファベットのaからdまでが、記号「#」に置換されるはずです。ちなみに、パターンの末尾にある「g」を削除して実行すると、最初に一致した文字(「a」)しか置換されません。
ここで注目したいのが、「[abcd]」とはせずに、「-」で範囲指定していることです。アルファベットの小文字すべてならば「[a-z]」、数字の0から4ならば「[0-4]」のように記述します。
- – - – -
$ echo ‘abcdefghi’ | sed ‘s/[a-d]/#/g’
####efghi
- – - – -
反対に、括弧内に含まれる1文字に一致しない、という条件を設けることもできます。以下に示すコマンド実行例の場合、「abcdefghi」のうちaからdに一致しない部分が置換され、戻り値は「abcd#####」となります。
- – - – -
$ echo ‘abcdefghi’ | sed ‘s/[^a-d]/#/g’
abcd#####
- – - – -
次回は、もう少し応用的な使い方を紹介する予定です。
第57回 MOSA Software Meeting 2009 補遺
東京は大橋会館にて開催された、毎秋恒例の「MOSA Software Meeting」。私も講師として参加、「Snow LeopardのMOSA的鑑賞法」なるテーマで90分ほど話をさせていただきました。今回は、その際話しきれなかったこと、緊張のあまり話そびれてしまったことについて、書かせていただこうと思います。
・過ぎ去りし機能たち 外伝
OSのメジャーバージョンアップといえば、新しい機能にばかり目が向きがちですが、消えた機能も多数あります。
まずはZFSについて。前々回、/usr/sbin/zfsや/usr/sbin/zpoolが取り去られたことをお伝えしましたが、その後「ZFS on OS X」プロジェクト自体が終了してしまいました。10月28日現在、ホスティング元のMacOS forgeには、近々メーリングリストとリポジトリを削除する旨の短いメッセージが残されているのみです。傍観していたかぎりでは、開発者間のやり取りに「終末感」は感じられませんでしたが、ぞろ息を吹き返して次のOSに採用される、という可能性は限りなくゼロに近いと思います。
終わりといえば、AppleTalk。DTP屋さんはいざ知らず、ファイル共有をAppleTalk(EtherTalk)経由で利用しているユーザはごく少数なはず。いわんやモサ伝読者をや。システム環境設定の「プリントとファクス」および「ネットワーク」ペインには、もうAppleTalkの項目はありません。atstatusやatlookupなどのコマンドも削除されました。そうそう、Mac OS Xの初期バージョンでは、用例に「examples: appleping ‘John Sculley:Macintosh SE@Pepsi’」と表示されていたapplepingコマンドも、消え去っています。
Xcode 3.2では、CarbonとJava、RubyにPythonのテンプレートが削除されました。Cocoa-PythonとCocoa-Rubyのブリッジも見当たりません。RubyCocoaの場合、テンプレートを追加すれば新規プロジェクトを作成できるようですが……それにしても、Xcode関連の話題については用意しておいたネタの大半を消化できず(場慣れしていないせいか時間配分がダメダメ)。セッションに参加してくださった方には、申し訳ありません。
・静的アナライザ 補遺
Snow LeopardでバージョンアップしたXcode 3.2ですが、注目度の高い新機能として「静的アナライザ」が挙げられます。ビルド設定で静的アナライザをチェックするか、メニューから[ビルド]→[Build and Analyze]を選択すれば実行できます。
その精度ですが、100%には(遠く?)及ばないにしても、ある程度役立つことは確かなようです。オープンソースソフトウェアのChangelogをたよりに、方々探し回ったところ、2ちゃんねるブラウザの「BathyScape」ではメモリリークの発見に貢献したそうですし、テキストエディタ「CotEditor」でも自作部分の未使用変数/未初期化変数/メモリリーク排除に役立ったそうです(こちらはXcode 3.2リリース前の話ですが)。うっかりメモリを解放し損ねることが少しでも減るとしたら、メモリーがタイトなiPhoneアプリの開発者にとってはマストな存在になるのではないでしょうか。
・HFS Plusの圧縮機能
公式な(NDAのしがらみがない)文書において、HFS Plusの仕様に変更が加えられたことはほとんど触れられていませんが、注意深くシステム上のあちらこちらに目を通すと、それなりの「証拠」を発見できます。その1つが、dittoコマンドのオンラインマニュアルです。
dittoコマンドには、新たに「–hfsCompression」オプションが追加されています。このオプションを有効にすると、コピー/抽出先のボリュームが圧縮機能をサポートしている場合、データが圧縮されます。ほかにも、「–preserveHFSCompression」など、圧縮関連のオプションが追加されていますので、近日中にまとめた記事を公開したいと思います。
第56回 Appleが発信するオープンソースソフトウェア
Mac OS Xというオペレーションシステムには、「オープン」と「プロプライエタリ」な技術が同居しています。今回は、Apple発のオープンソースソフトウェアを紹介しつつ、それが他のOS/アプリケーションに与える影響を考えてみます。
・Grand Central Dispatch(libdispatch)
Snow Leopardで投入された、メニーコア環境に適したスレッド配分を行う並列処理フレームワーク「Grand Central Dispatch」(GCD)は、その一部を構成する「libdispatch」がオープンソース化されています。ソースコードは、Mac OS X向けオープンソース開発のポータルサイト「MacOS forge」にて公開、ライセンスにはApache v2.0が適用されるため、自由な改変および再配布が可能です。
GCDは、Mac OS X/Darwinのカーネル(xnu)と、ランタイムであるlibdispatchの両輪で機能するため、GCDと同等の機能を他のOSで実現するにはカーネルレベルでの対応も必要です。libdispatchがオープンソース化されても、移植が完了するまでは多少の時間が必要だろうと思われましたが、早くもFreeBSDプロジェクトにより移植されました。libdispatchのオープンソース化が9月10日前後、FreeBSD Devsummitで行われたFreeBSD 9-CURRENTでの動作報告が9月18日ですから、数日で移植に関する目鼻立ちが整った、と見ていいでしょう。
FreeBSDプロジェクトのレポートに目を通してみますと、kqueue()にいくつかの命令をくわえたほか、libdispatchをMachセマフォからPOSIXセマフォに変更したことなどが挙げられています。
GCDのFreeBSD移植版は、CURRENTからSTABLEブランチへの合流(MFC)が行われたあと、FreeBSD 8.1-RELEASEから正式な機能として提供される見込みです。Mac OS X以外のOSで動作するということは、GCDという実装が普及すること、ひいては対応アプリケーションが増えることを意味するはずですから、我々も期待して見守りたいものです。
・WebKit
WebKitは、Safariにも採用されているHTMLレンダリングエンジンです。MOSAの方々にしてみれば、言わずと知れた存在と言っていいはずです。KDEプロジェクトで開発がスタートしたKHTMLをベースとし、HTMLパーサ/レンダラたるWebCoreと、JavaScriptエンジンのJavaScriptCoreで構成され……といった概要説明は他所をあたっていただくとして、ここではGCD同様、Mac OS X以外でどのように利用されているかに絞り見てみましょう。
まずはフレームワーク/APIでの採用が挙げられます。Nokia傘下のQt Software(旧Trolltech)が提供するGUIフレームワーク「Qt」では、バージョン4.4以降でWebKitの成果をマージし、「QtWebKit」として実装しました。QtのライバルといえるGTK+にも移植され(WebKit/GTK+)、GnomeのWebブラウザ「Epiphany」ではGeckoに代わるレンダリングエンジンとして採用されています。
Mac OS Xユーザに直接関係するところでは、Adobe AIRでの採用が挙げられます。WebKitはクロスプラットフォーム指向であり、HTML 5の機能を多く取り込んでおり、メンテナンスが比較的容易 — 前述したEpiphanyの開発メンバーは、Geckoのリリースサイクルの長さとメンテナンスの不便さをWebKitに変えた理由として挙げています — なことから、オープンソースのエコシステムに適していると評価されたのでしょう。
WebKitの採用は、PCの分野にとどまりません。iPhone OSはもちろんのこととして、Googleの「Android」、Palmの「WebOS」にも採用されています。そもそものルーツはKDEにありますが、現在利用されている機能の多くがApple主導のもと開発されたことを考えると、もっとも成功/普及しているApple発のオープンソースソフトウェアと言っていいのではないでしょうか。
第55回 Snow Leopardの変更点(2)
・Terminalの変更点
Snow Leopardの「Terminal」は、若干の機能強化が図られました。操作性の面では「ウインドウ分割機能」が追加され、画面を上下方向へ複数に分割することが可能になりました。画面上半分を固定して同じ情報を表示させておき、それを眺めつつ複数回にわたりコマンドを実行する、という使い方が可能になります。複数のウインドウではスマートではなく、複数のタブに分けては同時に見ることができない、というジレンマがこれで解消されます。
ウインドウ分割機能を利用する場合には、ショートカットキー (Command-D) を押すか、ウインドウ右端のスクロールバー上にある「日」に似たボタンをクリックします。分割を解除する場合はSHIFT-Command-D、あるいは「日」の下に表示される「□」に似たボタンをクリックします。
デフォルトの等幅フォントが「Menlo」に変更されたことも、ポイントかもしれません。従来のMonacoもバランスのいい、なにより見慣れたフォントだけに、敢えて変更する必要性は感じられませんが、わずかに行間が詰まって見えるところは、ソースコードの表示に適しているかもしれません。
・ZFSが消えた、しかし……
かつてあれだけ喧伝されていた、Solaris由来の次世代ファイルシステム「ZFS」ですが、クライアント版のSnow Leopardではあっさりと姿を消しています。リードオンリーながら/usr/sbinに置かれていた「zfs」も「zpool」も、Snow Leopardには収録されていません。
Mac OS X向けにZFSを移植するオープンソースプロジェクトとしての情報は、MacOS Forgeにホスティングされている「ZFS on OS X」プロジェクトに集約されています。ここのところコードの内容に大きな変化はないようですが、興味深いのはディスカッションコーナーの「zfs-discuss」。登録メンバーしか読むことのできないMOSADeN Onlineですが、NDA的にどうなのよ、という正式リリース前の状況があれこれ暴露されていたり、(Oralceの)BTRFSの話を持ち出す人物がいたりで、特に9月の投稿は読み応えがあるものとなっています。多少フィルタしなければならない話とはいえ、特に前触れもなく消えたZFSであるだけに、興味深いところです。
・rootになれない?
Mac OS Xには、古来UNIX系OSに存在し続ける管理者ユーザ「root」が存在しません。正確には存在するのですが、一般ユーザに管理者権限を一時的に貸与する「sudo」を採用したために、デフォルトでは無効化されてるのです。
セキュリティが脆くなることと引き換えになってもrootを有効にしたい、というユーザの要望に対してAppleは、NetInfoが存在したときには「NetInfoマネージャ」を、NetInfo廃止後は「ディレクトリユーティリティ」を提供していました。しかしSnow Leopardには、アプリケーション:ユーティリティにあるべきディレクトリユーティリティが存在しません。
というのもSnow Leopardでは、おそらく利用頻度が低いという理由で、いくつかのアプリケーションが/System/Library/CoreServicesに移動しているのです。ディレクトリユーティリティもこちらに移動しているので、必要なときはCoreServicesフォルダを開き利用することになります。
なお、Terminalを使えば、ディレクトリユーティリティを利用することなくrootを有効にできます。原則としてsudoを使うMac OS Xでは、敢えてrootを有効にすることはありませんが、どうしても必要ならば以下のコマンドを実行します。
- – - – -
$ sudo passwd root
- – - – -
第54回 Snow Leopardの変更点(1)
モサ伝がWebに移行して初の更新となる今回、偶然にもSnow Leopardのリリースとタイミングが重なりました。折角ですから、ターミナルを通じてSnow Leopardの変更点を眺めてみることにします。
・カーネルのバージョンを調べる
Mac OS X / Darwinには、システム情報を調べるためのコマンドが2つ用意されています。1つはUNIX系OSで一般的な「uname」コマンドで、「-v」オプションを付けて実行すると、OSの(ターミナルの場合はDarwinレイヤにあるカーネルの)バージョンを表示します。
- – - – -
$ uname -v
Darwin Kernel Version 10.0.0: Fri Jul 31 22:47:34 PDT 2009; root:xnu-1456.1.25‾1/RELEASE_I386
- – - – -
そしてもう1つが「hostinfo」です。オプションのないシンプルな実装のコマンドは、NeXTSTEP由来のもので、カーネルのバージョンのほかプロセッサ(コア)数や物理メモリ容量などのハードウェア情報まで出力されます。
・AppleTalkが消えた
Snow Leopardでは、ついにAppleTalkスタックが削除されました。もはや(システム環境設定の)ネットワークペインにもプリンタ登録画面にも現れません。AFP over TCP/IPが登場し、さらにRendezvouz(現Bonjour)が実装されたときから予想されていたことではありますが、1つの時代の終焉であることは確かです。
ターミナルで敢えてAppleTalkを使う必要性はほとんどありませんが、Leopardまでは「appleping」と「appletalk」コマンドが用意されていました。前者はAppleTalkノードの存在を確認するための(pingコマンドのAppleTalk版)、後者はAppleTalkのサービスを開始 / 停止するためのコマンドですが、Snow Leopardにはいずれのコマンドも収録されていません。
コマンドの有無を調べるときには、typeコマンドを利用します。使い方はかんたん、引数にコマンド名を指定しすればOKです。applepingとaplpetalkのいずれも、「not found」となるはずです。
- – - – -
$ type appleping
-bash: type: appleping: not found
- – - – -
・Mach-Oバイナリを調べる
アプリケーションあるいはコマンドがどのCPUアーキテクチャに対応しているかは、fileコマンドで確認できます。Finderの情報ウインドウに「Universal」や「Intel」の文字があるかどうかでも確認できますが、fileコマンドならば64bit対応も調べることができます。
使い方は極めてシンプル、引数に実行形式のファイル(バイナリ)を指定するだけでOKです。ただし、Mac OS Xではアプリケーションバンドル内のContents/MacOSディレクトリ以下に格納されているため、シェルの入力補完機能を使いながらでなければ手間がかかるかもしれません。以下のコマンド実行例はSafari 4のものですが、x86_64(64bit)とi386(32bit)の2つのCPUアーキテクチャに対応し、PowerPCには対応しないバイナリであることがわかります。
- – - – -
$ file /Applications/Safari.app/Contents/MacOS/Safari
/Applications/Safari.app/Contents/MacOS/Safari: Mach-O universal binary with 2 architectures
/Applications/Safari.app/Contents/MacOS/Safari (for architecture x86_64): Mach-O 64-bit executable x86_64
/Applications/Safari.app/Contents/MacOS/Safari (for architecture i386): Mach-O executable i386
- – - – -
Snow Leopardでは、多くのアプリケーションがx86_64とi386の2つのCPUアーキテクチャをサポートしています。iCalやシステム環境設定のように、PowerPCバイナリを収録しているアプリケーションもありますが、Leopard時代のi386/PPCという組み合わせから、i386/x86_64という組み合わせへと着実にシフトしました。なお、CarbonやCocoaなどの主要フレームワークは、Rosettaで実行するときの互換性を確保するために、ほとんどがPowerPCバイナリを収録しています。