2011年06月26日 ruby-1.9.x と encoding [長年日記]
_ ruby-1.9.x と encoding
ruby-1.8.x時代のスクリプトがruby-1.9.xだとエラーになるパターンが多々あるので、ruby-1.9.xのencoding関係(ソースとデータ)を短いスクリプトで検証してみた。
前提環境
$ echo $LC_ALL ja_JP.eucJP $
パターン 1
データはこれ。
$ cat test1.dat This is line 1. This is line 2. This is line 3. This is line 4. This is line 5. $ nkf -g test1.dat ASCII $
ソースはこれ。
$ cat test1.rb #! /usr/bin/ruby f = open("test1.dat","r") while (r = f.gets) if (/line 3/ =~ r) puts "matching line is #{r}" end end f.close $ nkf -g test1.rb ASCII $
結果はこれ。問題無し。
$ ./test1.rb matching line is This is line 3. $
パターン 2
ソースの中にマルチバイト文字を使ってみる。
$ cat test1.rb #! /usr/bin/ruby f = open("test1.dat","r") while (r = f.gets) if (/ライン3/ =~ r) puts "matching line is #{r}" end end f.close $ nkf -g test1.rb EUC-JP $
結果はこれ。エラー発生。
$ ./test1.rb ./test1.rb:4: invalid multibyte char (US-ASCII) ./test1.rb:4: invalid multibyte char (US-ASCII) ./test1.rb:4: syntax error, unexpected $end, expecting ')' if (/ライン3/ =~ r) ^ $
パターン 3
ソースのエンコーディングを指定してみる(2行目)。
$ cat test1.rb #! /usr/bin/ruby # coding: euc-jp f = open("test1.dat","r") while (r = f.gets) if (/ライン3/ =~ r) puts "matching line is #{r}" end end f.close $ nkf -g test1.rb EUC-JP $
結果はこれ。エラー回避に成功。
$ ./test1.rb $
パターン 4
データにマルチバイト文字を入れてみる。
$ cat test1.dat This is ライン1。 This is ライン2。 This is ライン3。 This is ライン4。 This is ライン5。 $ nkf -g test1.dat EUC-JP $
結果はこれ。問題無し。
$ ./test1.rb matching line is This is ライン3。 $
パターン 5
データのエンコーディングをutf-8にしてみる。
$ cat test1.dat | nkf -W -e This is ライン1。 This is ライン2。 This is ライン3。 This is ライン4。 This is ライン5。 $ nkf -g test1.dat UTF-8
結果はこれ。エラー発生。
$ ./test1.rb ./test1.rb:5:in `<main>': invalid byte sequence in EUC-JP (ArgumentError) $
パターン 6
オープン時にデータのエンコーディング(utf-8)を指定してみる。
$ cat test1.rb #! /usr/bin/ruby # coding: euc-jp f = open("test1.dat","r:utf-8") while (r = f.gets) if (/ライン3/ =~ r) puts "matching line is #{r}" end end f.close $ nkf -g test1.rb EUC-JP $
結果はこれ。エラー回避できず。
$ ./test1.rb ./test1.rb:5:in `<main>': incompatible encoding regexp match (EUC-JP regexp with UTF-8 string) (Encoding::CompatibilityError) $
パターン 7
オープン時にソースのエンコーディング(euc-jp)も指定してみる。
$ cat test1.rb #! /usr/bin/ruby # coding: euc-jp f = open("test1.dat","r:utf-8:euc-jp") while (r = f.gets) if (/ライン3/ =~ r) puts "matching line is #{r}" end end f.close $ nkf -g test1.rb EUC-JP $
結果はこれ。エラー回避に成功。
$ ./test1.rb matching line is This is ライン3。 $
番外
データの入力が標準入力の場合は`set_encoding'でエンコーディングを指定する。
$ cat test1.rb #! /usr/bin/ruby # coding: euc-jp STDIN.set_encoding("utf-8", "euc-jp") while (r = STDIN.gets) if (/ライン3/ =~ r) STDOUT.puts "matching line is #{r}" end end $ nkf -g test1.rb EUC-JP
結果はこれ。問題無し。
$ ./test1.rb <test1.dat matching line is This is ライン3。 $