BLOGTIMES
» ArchiveList (Tag for "ruby" )
«Prev || 1 · 2 · 3 · 4 · 5 · 6 · 7 ·... | | Next»
2014/08/21

Ruby 1.9.2 が EoL に

ruby  eol 

Ruby 1.9.2 が EoL になっていた*1のでメモ。
Ruby は生きているバージョンがちょっと分かりづらいですが、1.9.3 と 2.0.0 と 2.1.2 で良いんですかね。

Ruby 1.9.2系最後のリリース | マイナビニュース

Rubyコミュニティは8月19日(現地時間)、「Ruby 1.9.2-p330 Released」において、Ruby 1.9.2系の最新版となる「Ruby 1.9.2-p330」の公開を伝えた。今回のリリースはセキュリティ脆弱性の修正を目的としている。

at 21:34 |
2014/04/20

.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 対応なのでファイルが多い場合にはバッチで処理することができるので、エンジニアの人であればこちらのほうが汎用性が高いです。オープンソースなので、中身を見ようと思えばみられるところも良いですね。

ruby-msg - A library for reading and converting Outlook msg and pst files (mapi message stores). - Google Project Hosting

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 というコマンドが使えるようになっているので、下記のような感じでコンバートすることができます。

mapitool -i *.msg

Windows でお手軽に変換したい場合

上記の手順はエンジニアで ruby がある程度使いこなせることを前提にしているので、一般ユーザーの場合にはちょっと辛いかもしれません。そんなときには ruby-msg のプロジェクトが用意してくれている Windows 版のバイナリを使いましょう。下記のダウンロードサイトから、末尾が mswin32-stand_alone.zip というファイルをダウンロードして適当な場所に解凍しておきます。

コマンドライン操作が苦手な場合は mapitool.exe と同じフォルダに msg2eml.bat というファイルをテキストエディタで作成し、下記の内容を書き込んでおきます。あとは必要なファイルをこの msg2eml.bat にドラッグアンドドロップすれば、msg ファイルと同じフォルダに eml ファイルが生成されるはずです。

msg2eml.bat

cd /d %~dp0 mapitool.exe -i "%~1"

    at 18:08 |
    2014/03/13

    ls -f と Dir.glob()

    linux  cli  ruby 

    Linux などで ls -l とするとファイル名はきちんと辞書順で表示されるのに、他のプログラムでディレクトリをなめると出てくる順番がバラバラになるということにはずっと前から気になっていました。例えばタイムスタンプや日付でファイルを生成して、古い方から逐次処理しているつもりが・・・・・・というバグを出してしまったこともあります。

    そんなちょっと不思議な挙動の理由がやっと分かったのでメモ。例えば find コマンドの結果やRuby のプログラムで Dir.glob() を使ったりすると下記のような結果になります。

    $ mkdir bbb $ mkdir ccc $ mkdir eee $ ls bbb ccc eee $ find . -mindepth 1 -type d ./eee ./bbb ./ccc $ ruby -e 'puts Dir.glob("*")' eee bbb ccc

    これについては下記のエントリで 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() の結果と同じになりました。
    まだまだプログラマとしては青いことを痛感させられますね。


      at 22:12 |
      2014/02/19

      rbenv でインストールした ruby を cron から使う

      ruby 

      cron に仕込んだ ruby スクリプトを rbenv でインストールした ruby で起動させようとして試行錯誤したのでメモ。

      まず、rbenv が設定されている環境でシェルに ruby と打ち込むと実際に起動されるスクリプトは /usr/bin/ruby などの ruby 本体はなく、~/.rbenv/shims/rubyというシェルスクリプトになっています。ちょっと奇妙な感じがしますが、これが rbenv のミソで、この小さなシェルスクリプトが環境に応じてどの ruby の本体を呼び出すかという振り分けをしてくれています。

      $ which ruby ~/.rbenv/shims/ruby

      ここで、例えば /path/to/1.8.5dir というディレクトリと、/path/to/1.9.3dir というディレクトリを作って、前者はシステムデフォルト、後者は 1.9.3-p327 の ruby が起動するように設定しておきます。

      $ cd /path/to/1.8.5dir $ rbenv version system (set by /home/hsur/.rbenv/version) $ cd /path/to/1.9.3dir $ rbenv version 1.9.3-p327 $ rbenv version 1.9.3-p327 (set by /path/to/1.9.3dir/.ruby-version)

      起動した ruby のバージョンが分かるようにバージョンを吐くだけの下記のようなスクリプトを用意して、それぞれのディレクトリに置いておきます。先頭行を #!/bin/env ruby としている(つまり、PATH に従って ruby を探すようになっている)ことに注意してください。ここでうっかり #!/usr/bin/ruby などと書いてしまうと、呼び出される ruby の本体が /usr/bin/ruby に固定されてしまうのでバージョンが切り替わらなくなってしまいます。恥ずかしながら、ここでしばらくハマってしまいました。。。

      version.rb

      #!/bin/env ruby puts RUBY_VERSION

      ここで、テストのために下記の4つのエントリを crontab に追加します。ポイントは全ての行で export PATH="$HOME/.rbenv/shims:$HOME/.rbenv/bin:$PATH" を行って、rbenv 用の振り分けスクリプトを PATH に追加していることです。1,2 と 3,4 の違いはディレクトリに cd してから起動しているか、ダイレクトに ruby スクリプトを起動しているかの違いを確認するためのものです。

      * * * * * (export PATH="$HOME/.rbenv/shims:$HOME/.rbenv/bin:$PATH"; cd /path/to/1.8.5dir ; ./version.rb) | logger -i -t hoge1 -p local0.info * * * * * (export PATH="$HOME/.rbenv/shims:$HOME/.rbenv/bin:$PATH"; cd /path/to/1.9.3dir ; ./version.rb) | logger -i -t hoge2 -p local0.info * * * * * (export PATH="$HOME/.rbenv/shims:$HOME/.rbenv/bin:$PATH"; /path/to/1.8.5dir/version.rb) | logger -i -t hoge3 -p local0.info * * * * * (export PATH="$HOME/.rbenv/shims:$HOME/.rbenv/bin:$PATH"; /path/to/1.9.3dir/version.rb) | logger -i -t hoge4 -p local0.info

      仕込んでから一分ごとに syslog に下記のような行が出力されるはずです。

      Feb 19 21:55:02 sailane hoge1[30757]: 1.8.5 Feb 19 21:55:02 sailane hoge2[30753]: 1.9.3 Feb 19 21:55:02 sailane hoge3[30749]: 1.8.5 Feb 19 21:55:02 sailane hoge4[30746]: 1.9.3

      この方法だと cd してもしなくてもきちんとバージョンが切り替わることが確認できました。


        at 22:04 |
        2014/01/05

        rbenv をアップデートして最新の ruby をインストールできるようにする

        ruby 

        だいぶ前に rbenv を使って複数の ruby をインストールして切替えできるようにしましたが、先日 2.0.0-p353 をインストールしようと思って rbenv-install -l としたところ、一覧に 2.0.0-p353 が出てこずにいろいろと苦戦してしまったので、その顛末をメモ。rbenv は新しい Ruby がリリースされる度に更新されているので、rbenv 環境のアップデートが必要というオチでした。

        以前のエントリ通りにインストールしている場合には下記の要領でアップデートできます。ポイントとしては rbenv だけでなく、ruby-build もアップデートする必要があることです。僕の場合 rbenv と同じディレクトリにインストールしてしまっていたので、gitではアップデートできず、再度インストールをすることになりました。どちらにしてもそれほど時間はかかりません。

        $ cd ~/.rbenv/ $ git pull origin master # rbenv のアップデート $ cd ~ $ rm -rf working $ mkdir working $ cd working $ git clone git://github.com/sstephenson/ruby-build.git $ cd ruby-build $ PREFIX=~/.rbenv ./install.sh # ruby-build のアップデート

          at 20:03 |
          2013/10/03

          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

          require "enumerator" str = "foobarbazfoobarbaz" pat = /foo|baz/ matches = str.enum_for(:scan, pat).with_object({}){|m, t| t[Regexp.last_match.begin(0)] = m } p matches

          1.8.5 だと with_object() が使えないので、こんな感じでしょうか。
          そこはかとなくダサイ感じですが、今日のところはこの辺で。

          for_1_8.rb

          require "enumerator" str = "foobarbazfoobarbaz" pat = /foo|baz/ matches = {} str.enum_for(:scan, pat).each{|m| matches[Regexp.last_match.begin(0)] = m } p matches

            at 18:51 |
            2013/09/03

            Ruby 1.8 の文字列を slice したときにできる壊れたマルチバイト文字を取り除く

            ruby  programming 

            最近は Ruby 1.8.x を使うことも少なくなってきましたが、日本語を含んだ String を slice() を使って切り出そうとしてハマってしまったのでメモ。
            すっかり忘れていましたが、 Ruby 1.8 の String の slice() はマルチバイトとか関係なくバイト単位で無理矢理ぶった切ってしまうという仕様なのでした。

            具体的にはこんな感じの処理です。

            str = "あいうえお" p str[1,10]

            これを実行すると「あ」のマルチバイトの一部と、「え」のマルチバイトの一部が含まれた下記のような String が得られます。

            "\201\202いう・

            今回は特に綺麗にマルチバイトの文字を取り出したいというよりは、ゴミが出なければ OK という感じだったので、このゴミを取り除いてみます。

            先人の知恵を頼る

            昔からこの手の問題はあったと思うので、みんなどのようにこの問題に対処しているのかと思ってしらべてみたら正規表現を使って slice(/\A.{0,}/m) とするパターン*1が沢山出てきました。

            先ほどの例を書き換えてみるとこんな感じでしょうか。

            str = "あいうえお" p str[1,10].slice(/\A.{0,}/m)

            確かに末尾のゴミは消えたのですが、残念ながら行頭のゴミはそのままでした。

            "\201\202いう"

            NKF はどうだろうか

            仕方が無いので全く別のアプローチを試みることにします。
            壊れた文字列を取り除くという意味では一旦コード変換をかけて、戻したりすればいいのかなという単純な発想から NKF を使ってフィルタしてみることにしました。nkf はコード変換しなくてもいいみたいなので、UTF-8 -> UTF-8 に変換する -wW オプションを使っています

            require 'nkf' str = "あいうえお" NKF.nkf('-wW',str[1,10])

            これで壊れたマルチバイト文字を取り除くことができました。

            "いう"

            場合によっては文字が余計に取り除かれてしまうことがありますが、今回は気にしないことにします。


            at 17:35 |
            2013/07/01

            Ruby 1.8系 が EoL に

            ruby  eol 

            6月30日に長らく現役だった Ruby 1.8 系のメンテナンスが終了が発表されていました。

            OS のディストリビューションに入っているものはしばらく使えますが、ソースから入れるのは避けたほうが良さそうです。
            とはいってもまだ捨てられないものがいくつかあるので、いましばらくは動作確認用に rbenv 環境 で活躍してもらう予定です。

            Ruby 1.8.7 は引退しました

            10年が経ち、1.8.7 がレガシーになったと言えることは非常に喜ばしいことです。 1.8.7 は歴史を作りました。 文字通り、我々の生活を変えました。 そして、我々は変わり続けるために、前に進んでいます。 Ruby 2.0.0 は大変すばらしいですが、来る 2.1 を一層魅力的なものとするため、1.8.7 を終焉させ、最先端の開発版である ruby trunk に注力していきます。

              at 19:14 |
              2013/03/31

              invalid byte sequence in Windows-31J が出たときは

              ruby  charset 

              以前も Ruby 1.9 の文字コード周りは Encoding::CompatibilityError にハマったり、Encoding::UndefinedConversionError にハマったりしましたが、今日は invalid byte sequence in Windows-31J というエラーにどっぷりとハマってしまいました。コードは極簡単な TSV を読み取って表示するだけのもの。

              hoge.rb

              require 'csv' CSV.foreach('hoge.txt', :headers => true, :col_sep=>"\t") do |row| puts row end

              これを実行するとこんな感じになってしまいます。

              C:\>jruby hoge.rb ArgumentError: invalid byte sequence in Windows-31J =~ at org/jruby/RubyRegexp.java:1487 =~ at org/jruby/RubyString.java:1715 init_separators at c:/jruby-1.7.3/lib/ruby/1.9/csv.rb:2058 initialize at c:/jruby-1.7.3/lib/ruby/1.9/csv.rb:1590 open at c:/jruby-1.7.3/lib/ruby/1.9/csv.rb:1349 foreach at c:/jruby-1.7.3/lib/ruby/1.9/csv.rb:1207 (root) at hoge.rb:3

              これは Encoding.default_external と実際の文字コードがずれているために発生するようなので、起動時に -E オプションで文字コードを指定してやるか、

              ruby -Eutf-8 hoge.rb

              もしくは下記のように Encoding.default_external の値をファイル内の文字コードと合わせてやればいいようです。

              Encoding.default_external = 'UTF-8'

              File.open() を使う場合には、File.open('hoge.txt', 'r:utf-8') という感じで、モード設定のところに文字コードが指定できます。
              今回は -E でオプションを設定してみたところ、うまくいきました。

              C:\>jruby -Eutf-8 hoge.rb ほげ,ふが

              参考


                at 22:32 |
                2012/08/05

                ERB と binding

                ruby 

                先日のFE覚醒誕生日カレンダーは下記のような簡単な Ruby スクリプトを使って、リストから .ics ファイルを生成し、そのファイルを Google カレンダーにインポートしました。

                こういう定型的なテキスト出力を伴う処理を大量に行うときは ERB*1 のようなテンプレートエンジンが大活躍です。ERB を使うのは久しぶりだったのですが、この binding が何者なのかというのは前々からちょっと気になっていました。ERB#result は binding がなくても呼び出せますが、それだとうまく変数が参照できないので、一種のおまじないだと思っていました。

                puts @erb.result(binding)

                特にスクリプト中で binding という変数は作っていないので、これが何なのか irb で調べてみます。Binding*2というクラスのオブジェクトでした。

                $ irb irb(main):001:0> binding => #<Binding:0xb7f0c690> irb(main):002:0>

                マニュアルを読み進めてみると、この binding というのは Kernel#bindingModule: Kernel (Ruby 1.9.3) を呼び出して Binding オブジェクトを取得していたようです。Binding オブジェクトは「ローカル変数のテーブルと self、モジュールのネストなどの情報を保 持するオブジェクト」ということになっているので、erb はこれを使って result が呼ばれた時の変数にアクセスするという仕組みになっていたのですね。

                [ERB と binding の続きを読む]

                at 23:11 |
                «Prev || 1 · 2 · 3 · 4 · 5 · 6 · 7 ·... | | Next»
                » ArchiveList (Tag for "ruby" )