Rubyを使って開発工数を短縮しよう

開発担当の佐藤Sです。

プログラマの皆さんに質問です。Rubyを使ったことはありますか?
プログラマであればRubyがどんなプログラミング言語なのか、知識としてはご存知のことと思います。ですが、非ウェブ系開発者だと、意外と使用経験のない方は多いのではないでしょうか。

例えば、指定フォルダにあるすべてのPNGファイルのコメントを抽出してCVSファイルに出力する という処理が必要になったとしましょう。
技術的には全く高度ではないものの、例えばCやC++などで書こうと思うとちょっと面倒です。

Rubyはスクリプト言語なので文字列処理向き、というイメージがあるかも知れませんが、そんなことはありません。豊富なライブラリが揃っているので、ちょっと面倒な処理でも、意外とシンプルに書くことができるのです。

スクリプト言語なので、コンパイルなしで実行できるという手軽さもメリットのひとつです。
実行時のパフォーマンスが要求されるプログラムならともかく、特に1回だけの使い切りプログラムやちょっとしたデータ変換処理などには、少しの労力で目的を達成できるRubyはオススメです。

Rubyのインストール

本記事では、Windows上で実行した例を示します。簡単にインストール手順をご紹介しておきます。
http://www.artonx.org/data/asr/ からRuby 1.9.3p362のパッケージをダウンロード、インストールを行います。(2012/12現在)
パスを通して、コマンドラインでruby -vと入力して以下が確認できればインストール完了です。インストールには管理者権限が必要な場合があるのでご注意ください。

ruby 1.9.3p362 (2012-12-25) [i386-mswin32_100]
本サンプルはWindows上、Ruby 1.9.3p362で実行しています(エラー処理は省略しています)。
1.8系でも動作することは確認しています。
それでは早速、Rubyで書いたプログラムをご紹介しましょう。

ケース1

要求:指定フォルダにあるすべてのPNGファイルのコメントを抽出してCVSファイルに”ファイル名,コメント”の形式で出力したい

本当はRMagickを使うともっと短くなるのですが、それでは面白くない(C,C++ユーザーにRubyの文法の面白さを見てもらいたい)ので、敢えてRubyでPNGファイルを解析してみます。

  • pngcomment2csv.rb
# -*- coding: utf-8 -*-
#指定ディレクトリ以下のPNGファイルのコメントをCSVへ書き出すスクリプト

require "csv"

#出力CSVファイル名
FILE_RESULT = "result.csv"

CHUNK_TEXT = "tEXt"
KEYWORD = "Comment"

#PNGファイルにコメントがあったら取得
def get_pngcomment file
  #PNGファイルオープン
  open(file, "rb") do |f|
    #PNGファイルか?
    head = f.read 8
    break if head.unpack("CA3C4") != [0x89, "PNG", 0x0d, 0x0a, 0x1a, 0x0a]

    #チャンクループ
    while data = f.read(4) do
      #長さ読み込み
      len = data.unpack "N"
      #チャンク読み込み
      chunk = f.read 4

      #目的のチャンクか?
      if chunk == CHUNK_TEXT
        data = f.read len[0]
        #crc
        f.seek 4, IO::SEEK_CUR

        #keyword + "\0" + textなので分割
        text = data.split "\0"
        #目的のキーワードでなければスキップ
        next if text[0] != KEYWORD

        return text[1]
      else
        #skip data + crc
        f.seek len[0] + 4, IO::SEEK_CUR
      end
    end
  end
  return nil
end

#main

#CSVファイルオープン
CSV.open(FILE_RESULT, "w") do |w|
  #ファイル列挙
  Dir.glob(ARGV[0] + "/*.png").each do |f|
    #ベースファイル名と取得したコメントをCSVへ出力
    w << [File::basename(f), get_pngcomment(f)]
  end
end

以下のように実行

ruby pngcomment.rb d:/work/png/

出力結果、result.csv

frame.png,"Ikebukuro, Japan"
parts1.png,comipo body
parts2.png,kaname face

注目点は、CSVクラスが’,'(カンマ)の面倒を見てくれており、カンマを含む項目がダブルクォートでちゃんと括られているところです。

ケース2

要求:渡された簡単なXMLファイルをJSON形式に変換したい、その際にauthor項目を追加したい
  • xml2json.rb
# -*- coding: utf-8 -*-
#XMLファイルをJSONへ変換するスクリプト

require "rubygems"
require "active_support/core_ext"

AUTHOR = "comipo chan"

#ファイルを一括読み込み
xml = File.read ARGV.first

#XMLをハッシュへ変換
hash = Hash.from_xml xml

#author項目を挿入
hash["author"] = AUTHOR

#ハッシュをJSONへ変換
json = hash.to_json

#文字列に変換して出力
puts json.to_s

なお、このスクリプトでは外部パッケージを使用しているため、事前に必要パッケージを以下の手順でインストールをしておく必要があります。

gem install active_support
gem install i18n

変換元のXML、sample.xml

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<items>
	<item1>OPTPiX imesta</item1>
	<item2>Sprite Studio</item2>
	<item3>EXEpress</item3>
</items>

以下のように実行

ruby xml2json.rb sample.xml
出力結果、sample.json
{"items":{"item1":"OPTPiX imesta","item2":"Sprite Studio","item3":"EXEpress"},"author":"comipo chan"}

整形するとこんな感じ

{
	"items" : {
		"item1" : "OPTPiX imesta",
		"item2" : "Sprite Studio",
		"item3" : "EXEpress"
	},
	"author" : "comipo chan"
}

おまけ、ワンライナーにすると以下のようになります。クォートの扱いに注意が必要です。

ruby -r 'rubygems' -e 'require "active_support/core_ext"' -e 'xml = File.read ARGV.first; hash = Hash.from_xml xml; hash["author"] = "comipo chan"; puts hash.to_json.to_s' sample.xml

いかがでしょう。

わずかなステップで大きな結果が得られることがおわかりいただけたでしょうか。みなさんも開発ツールとして Ruby を使い、生産性向上を図ってみてはいかがでしょう。

他にもさまざまなスクリプト言語があり、ほぼ同様のことはできると思います。ぞれぞれ特長があり、向き不向きもあることでしょう。自分の用途に合った使いやすいスクリプト言語を探しているなら、Ruby もぜひ試してみてください。

タグ , | 2020/06/16 更新 |