はじめて触ったRubyでTSVをマスキング処理。

2016.10.23

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

基幹などからデータベースにロードする際に「0000-0000-0000」を「****-****-0000」の様にマスキングしたい場合があります。
Rubyは触ったことが無かったのですが、案件にRubyが関わってきそうだったので後学のためにもRubyで実現する方法を調べました。
ちなみにRailsではありません。

目的

TSVファイルを読み込み、カラム「number」に該当する値を「0000-0000-0000」から「****-****-0000」に置換してTSVファイルを出力する。

環境

Mac OSX 10.10.5 Yosemite
Ruby 2.3.0

TSV

masking_test.tsv

id	name	number
1	josh milan	1111-1222-1333
2	kevin hedge	2111-2222-2333
3	chris herbert	311-322-3333

id=3のnumberだけ他と桁数が違いますが、この状態でマスキングを行います。
一人だけ古い口座番号を使っている、みたいなイメージです。

Ruby

blog_test.rb

require 'csv' 

#1、TSVを出力
File.open("blog_test.tsv", "w") do |outFile|

  #2、TSVを読み込む
  file = ARGV[0]
  tsvDatas = CSV.read(file, col_sep: "\t", headers: false)

  #3、ヘッダー出力
  data = tsvDatas[0]
  for i in 0...data.size do
    if i < data.size-1
      outFile.print(data[i] + "\t")
    else
      outFile.puts(data[i])
    end
  end

  #4、レコードごとの処理
  for i in 1...tsvDatas.size do

    str = ""

    #4-1
    tsv1 = tsvDatas[i]
    #4-2 
    number = tsv1[2] 
    #4-3
    numArray = number.split("-") 

    for i in 0...numArray.length do

      if i != (numArray.length-1)
        
        size = numArray[i].size
        
        #4-4      
        for k in 0...size do
          str << "*"
        end
        str << "-"

      else
        
        #4-5
        str << numArray[i]
        
      end
      
    end

    #4-6
    outFile.puts( tsv1[0] + "\t" + tsv1[1] + "\t" + str )
    
  end

  #5、TSV出力処理終了
  outFile.close
end

解説

1、TSVを出力

File.open("blog_test.tsv", "w") do |outFile|
...
end

2、TSVファイル読み込み 元ファイルはTSVですが、CSVというライブラリをrequireで読み込みます。

require 'csv'

ARGV[0]でコマンド引数(ファイルパス)を取得し、内容を配列で取得。
CSV.read(第1引数:ファイルパス、第2引数:区切り文字、第3引数:trueで1行目をヘッダーとする)

file = ARGV[0]
tsvDatas = CSV.read(file, col_sep: "\t", headers: false)

3、ヘッダーをファイルに出力 配列からヘッダーの行だけ取得し、forでカラム名を一つづつ取得。
TSVなので最後のカラム名以外は"\t"を追加しています。

  data = tsvDatas[0]
  for i in 0...data.size do
    if i < data.size-1
      outFile.print(data[i] + "\t")
    else
      outFile.puts(data[i])
    end
  end

forは下記の様にも書けます。

(0...data.size).each do |i|
  ...処理内容
end

4、レコードごとの処理
下記の処理を表しています。
4-1、TSVの内容から1行(1, josh milan, 1111-1222-1333)を抽出
4-2、そこから口座番号を抽出(1111-1222-1333)
4-3、口座番号を「-」で分割して配列に(1111, 1222, 1333)
4-4、配列の最後以外([1111, 1222])はそれぞれの桁数分を「*」にして、用意した変数strに入れる(****-****-)
4-5、配列の最後だけそのまま変数strに入れて(****-****-1333)、一行分の口座番号をマスキング完了
4-6、id、名前、口座番号をTSV形式にしてファイルに出力
TSV次の1行に進んで終わるまで同じ処理を繰り返し。

5、TSV出力処理終了

outFile.close

実行

実行文

$ ruby blog_test.rb masking_test.tsv

blog_test.tsv

id	name	number	
1	josh milan	****-****-1333
2	kevin hedge	****-****-2333
3	chris herbert	***-***-3333

さいごに

自分の基本がJavaなのでEclipseの様なIDEを使えなくてもどかしくなりましたが何とか仕上げました。
基礎から教えてくれる動画サイトがとても参考になりました。
ドットインストール | Ruby入門 (全26回)