- blogs:
- cles::blog
Ruby 1.9.2 が EoL に
ruby
eol Ruby 1.9.2 が EoL になっていた*1のでメモ。
Ruby は生きているバージョンがちょっと分かりづらいですが、1.9.3 と 2.0.0 と 2.1.2 で良いんですかね。
Rubyコミュニティは8月19日(現地時間)、「Ruby 1.9.2-p330 Released」において、Ruby 1.9.2系の最新版となる「Ruby 1.9.2-p330」の公開を伝えた。今回のリリースはセキュリティ脆弱性の修正を目的としている。
.msg を .eml に変換する (ruby-msg編)
migration
ruby
msoffice
bat
rfc Outlook のメールファイルである .msg を他のメーラーで読める .eml 形式に変換する方法については以前にも Outlook Export Tool を使う方法や MSG To EML Converter を使う方法を取り上げましたが、どちらもちょっと怪しい無料のソフトウェアを使わなければならないのが欠点と言えば欠点でした。
今回は ruby-msg という pure ruby で書かれたライブラリを使って .msg を .eml に変換します。pure ruby なので、プラットフォーム非依存かつ、CLI 対応なのでファイルが多い場合にはバッチで処理することができるので、エンジニアの人であればこちらのほうが汎用性が高いです。オープンソースなので、中身を見ようと思えばみられるところも良いですね。
Generally, the goal of the project is to enable the conversion of msg and pst files into standards based formats, without reliance on outlook, or any platform dependencies. In fact its currently pure ruby, so it should be easy to get running.
It is targeted at people who want to migrate their PIM data from outlook, converting msg and pst files into rfc2822 emails, vCard contacts, iCalendar appointments etc. However, it also aims to be a fairly complete mapi message store manipulation library, providing a sane model for (currently read-only) access to msg and pst files (message stores).
gem になっているのでインストールは gem install ruby-msg で一撃です。
インストールが終わると mapitool というコマンドが使えるようになっているので、下記のような感じでコンバートすることができます。
† Windows でお手軽に変換したい場合
上記の手順はエンジニアで ruby がある程度使いこなせることを前提にしているので、一般ユーザーの場合にはちょっと辛いかもしれません。そんなときには ruby-msg のプロジェクトが用意してくれている Windows 版のバイナリを使いましょう。下記のダウンロードサイトから、末尾が mswin32-stand_alone.zip というファイルをダウンロードして適当な場所に解凍しておきます。
コマンドライン操作が苦手な場合は mapitool.exe と同じフォルダに msg2eml.bat というファイルをテキストエディタで作成し、下記の内容を書き込んでおきます。あとは必要なファイルをこの msg2eml.bat にドラッグアンドドロップすれば、msg ファイルと同じフォルダに eml ファイルが生成されるはずです。
msg2eml.bat
ls -f と Dir.glob()
linux
cli
ruby Linux などで ls -l とするとファイル名はきちんと辞書順で表示されるのに、他のプログラムでディレクトリをなめると出てくる順番がバラバラになるということにはずっと前から気になっていました。例えばタイムスタンプや日付でファイルを生成して、古い方から逐次処理しているつもりが・・・・・・というバグを出してしまったこともあります。
そんなちょっと不思議な挙動の理由がやっと分かったのでメモ。例えば find コマンドの結果やRuby のプログラムで Dir.glob() を使ったりすると下記のような結果になります。
これについては下記のエントリで ls のソースコードはもちろんのこと、 strace による解析や Perl の内部構造についても詳細に解説されています。これはとても良い教材になりそうです。結論としては ls がデフォルトで、ls が出力結果をソートするようになっているだけということのようです。ちなみにこのソートは -f オプションをつけるとオフにできるとのこと。
ls のソースを読んでプログラマになりました - ablog
こちらも getdents を呼んでいる。Perl の readdir も ls も getdents システムコールを呼んでるけど、ls はソートしていると思われる。ls の man を見ると、デフォルトでアルファベットでソートされ、-f オプションをつけるとソートされないと書かれている。
ls に -f オプションをつけると Perl の readdir と同じ順になった。
試しに ls に -f をつけてみると、find や Dir.glob() の結果と同じになりました。
まだまだプログラマとしては青いことを痛感させられますね。
rbenv でインストールした ruby を cron から使う
ruby cron に仕込んだ ruby スクリプトを rbenv でインストールした ruby で起動させようとして試行錯誤したのでメモ。
まず、rbenv が設定されている環境でシェルに ruby と打ち込むと実際に起動されるスクリプトは /usr/bin/ruby などの ruby 本体はなく、~/.rbenv/shims/rubyというシェルスクリプトになっています。ちょっと奇妙な感じがしますが、これが rbenv のミソで、この小さなシェルスクリプトが環境に応じてどの ruby の本体を呼び出すかという振り分けをしてくれています。
ここで、例えば /path/to/1.8.5dir というディレクトリと、/path/to/1.9.3dir というディレクトリを作って、前者はシステムデフォルト、後者は 1.9.3-p327 の ruby が起動するように設定しておきます。
起動した ruby のバージョンが分かるようにバージョンを吐くだけの下記のようなスクリプトを用意して、それぞれのディレクトリに置いておきます。先頭行を #!/bin/env ruby としている(つまり、PATH に従って ruby を探すようになっている)ことに注意してください。ここでうっかり #!/usr/bin/ruby などと書いてしまうと、呼び出される ruby の本体が /usr/bin/ruby に固定されてしまうのでバージョンが切り替わらなくなってしまいます。恥ずかしながら、ここでしばらくハマってしまいました。。。
version.rb
ここで、テストのために下記の4つのエントリを crontab に追加します。ポイントは全ての行で export PATH="$HOME/.rbenv/shims:$HOME/.rbenv/bin:$PATH" を行って、rbenv 用の振り分けスクリプトを PATH に追加していることです。1,2 と 3,4 の違いはディレクトリに cd してから起動しているか、ダイレクトに ruby スクリプトを起動しているかの違いを確認するためのものです。
仕込んでから一分ごとに syslog に下記のような行が出力されるはずです。
この方法だと cd してもしなくてもきちんとバージョンが切り替わることが確認できました。
rbenv をアップデートして最新の ruby をインストールできるようにする
ruby だいぶ前に rbenv を使って複数の ruby をインストールして切替えできるようにしましたが、先日 2.0.0-p353 をインストールしようと思って rbenv-install -l としたところ、一覧に 2.0.0-p353 が出てこずにいろいろと苦戦してしまったので、その顛末をメモ。rbenv は新しい Ruby がリリースされる度に更新されているので、rbenv 環境のアップデートが必要というオチでした。
以前のエントリ通りにインストールしている場合には下記の要領でアップデートできます。ポイントとしては rbenv だけでなく、ruby-build もアップデートする必要があることです。僕の場合 rbenv と同じディレクトリにインストールしてしまっていたので、gitではアップデートできず、再度インストールをすることになりました。どちらにしてもそれほど時間はかかりません。
Ruby で正規表現がマッチした場所と文字列を取得する
ruby
programming
regex 例えば foobarbazfoobarbaz という文字列に対して /foo|baz/ という正規表現マッチさせると foo と bar が2箇所ずつ合計4箇所マッチするわけですが、マッチした文字列とポジションを一緒に取得をする方法が Ruby にはないようだったので書いてみたら意外と面倒だったので、忘れないようにメモ。
ちょっとムダなことをしてるような気がしなくもないですが、一応できました。
どちらも実行すると {0=>"foo", 6=>"baz", 9=>"foo", 15=>"baz"} という感じになります。
for_1_9_or_later.rb
1.8.5 だと with_object() が使えないので、こんな感じでしょうか。
そこはかとなくダサイ感じですが、今日のところはこの辺で。
for_1_8.rb
Ruby 1.8 の文字列を slice したときにできる壊れたマルチバイト文字を取り除く
ruby
programming 最近は Ruby 1.8.x を使うことも少なくなってきましたが、日本語を含んだ String を slice() を使って切り出そうとしてハマってしまったのでメモ。
すっかり忘れていましたが、 Ruby 1.8 の String の slice() はマルチバイトとか関係なくバイト単位で無理矢理ぶった切ってしまうという仕様なのでした。
具体的にはこんな感じの処理です。
これを実行すると「あ」のマルチバイトの一部と、「え」のマルチバイトの一部が含まれた下記のような String が得られます。
今回は特に綺麗にマルチバイトの文字を取り出したいというよりは、ゴミが出なければ OK という感じだったので、このゴミを取り除いてみます。
† 先人の知恵を頼る
昔からこの手の問題はあったと思うので、みんなどのようにこの問題に対処しているのかと思ってしらべてみたら正規表現を使って slice(/\A.{0,}/m) とするパターン*1が沢山出てきました。
先ほどの例を書き換えてみるとこんな感じでしょうか。
確かに末尾のゴミは消えたのですが、残念ながら行頭のゴミはそのままでした。
† NKF はどうだろうか
仕方が無いので全く別のアプローチを試みることにします。
壊れた文字列を取り除くという意味では一旦コード変換をかけて、戻したりすればいいのかなという単純な発想から NKF を使ってフィルタしてみることにしました。nkf はコード変換しなくてもいいみたいなので、UTF-8 -> UTF-8 に変換する -wW オプションを使っています。
これで壊れたマルチバイト文字を取り除くことができました。
場合によっては文字が余計に取り除かれてしまうことがありますが、今回は気にしないことにします。
Ruby 1.8系 が EoL に
ruby
eol 6月30日に長らく現役だった Ruby 1.8 系のメンテナンスが終了が発表されていました。
OS のディストリビューションに入っているものはしばらく使えますが、ソースから入れるのは避けたほうが良さそうです。
とはいってもまだ捨てられないものがいくつかあるので、いましばらくは動作確認用に rbenv 環境 で活躍してもらう予定です。
10年が経ち、1.8.7 がレガシーになったと言えることは非常に喜ばしいことです。 1.8.7 は歴史を作りました。 文字通り、我々の生活を変えました。 そして、我々は変わり続けるために、前に進んでいます。 Ruby 2.0.0 は大変すばらしいですが、来る 2.1 を一層魅力的なものとするため、1.8.7 を終焉させ、最先端の開発版である ruby trunk に注力していきます。
invalid byte sequence in Windows-31J が出たときは
ruby
charset 以前も Ruby 1.9 の文字コード周りは Encoding::CompatibilityError にハマったり、Encoding::UndefinedConversionError にハマったりしましたが、今日は invalid byte sequence in Windows-31J というエラーにどっぷりとハマってしまいました。コードは極簡単な TSV を読み取って表示するだけのもの。
hoge.rb
これを実行するとこんな感じになってしまいます。
これは Encoding.default_external と実際の文字コードがずれているために発生するようなので、起動時に -E オプションで文字コードを指定してやるか、
もしくは下記のように Encoding.default_external の値をファイル内の文字コードと合わせてやればいいようです。
File.open() を使う場合には、File.open('hoge.txt', 'r:utf-8') という感じで、モード設定のところに文字コードが指定できます。
今回は -E でオプションを設定してみたところ、うまくいきました。
† 参考
- Windows環境でinvalid byte sequence in Windows-31Jになる場合(Ruby 1.9.2)ユニキャストラボ | ユニキャストラボ
- Ruby1.9をこれから使う人のためのM17Nまとめ - 仙台Rails牛タン社長
- Rubyのエンコーディング
ERB と binding
ruby 先日のFE覚醒誕生日カレンダーは下記のような簡単な Ruby スクリプトを使って、リストから .ics ファイルを生成し、そのファイルを Google カレンダーにインポートしました。
こういう定型的なテキスト出力を伴う処理を大量に行うときは ERB*1 のようなテンプレートエンジンが大活躍です。ERB を使うのは久しぶりだったのですが、この binding が何者なのかというのは前々からちょっと気になっていました。ERB#result は binding がなくても呼び出せますが、それだとうまく変数が参照できないので、一種のおまじないだと思っていました。
特にスクリプト中で binding という変数は作っていないので、これが何なのか irb で調べてみます。Binding*2というクラスのオブジェクトでした。
マニュアルを読み進めてみると、この binding というのは Kernel#bindingModule: Kernel (Ruby 1.9.3) を呼び出して Binding オブジェクトを取得していたようです。Binding オブジェクトは「ローカル変数のテーブルと self、モジュールのネストなどの情報を保 持するオブジェクト」ということになっているので、erb はこれを使って result が呼ばれた時の変数にアクセスするという仕組みになっていたのですね。
[ERB と binding の続きを読む]- sadpkv
- CACHEMANAGER.phpというのはどうだろうかと
- pairb1m
- Lightning のToDoリストを複数のPCで共有できるアドオン
- majodca
- 九州旅行から帰ってきました
- majodca
- 九州旅行から帰ってきました
- hot534
- yum を使って OpenVPN をインストールする
- dresssu3
- NP_Trackbackを騙るトラックバックspamについて
- zippern7o
- NP_SpamBayesJP jp1b
- park81o
- Google Docs をメールフォームとして使う
- fogmpl
- なんで官庁の文章はPDFなんだろうか
- cutjw9
- 即席スライドショーを作る
- frightenlho
- 添付ファイルの容量を表示する「Attachment Sizes」
2 . 福岡銀がデマの投稿者への刑事告訴を検討中(5064)
3 . GitHub が全ての公開リポジトリへのシークレットスキャンを有効に(4200)
4 . 年次の人間ドックへ(4132)
5 . 2023 年分の確定申告完了!(1つめ)(3990)
Academic[574]
Book[155]
Diary[522]
Disaster[101]
Foodlogue[1425]
Game[284]
Goods[805]
Healthcare[341]
Hobby[32]
IT[1195]
Military[343]
misc.[1570]
Mobile[510]
Music[38]
Neta[106]
News[95]
Photo[391]
RealEstate[120]
Security[1178]
SEO Contest[36]
Software[634]
Tips[1886]
Travelogue[1238]
Web[675]
Work[193]