こんにちは!Webコーダー・プログラマーの貝原(@touhicomu)です。
今日は、Rubyによるファイル出力・入力まとめとして、改行コード、CSV、配列の使い方について解説したいと思います。
この記事では、
- 改行コードをprintする方法
- 改行コードをchompで取り除く方法
- 改行コードをgsubで取り除く方法
という基本的な内容から、
- 改行コード付きのファイルを入力する方法
- 改行コード付きでファイルへ出力する方法
- CSVとして入力・出力する方法
などの応用的な使い方に関しても学習していきます。
このページで、Rubyの改行コード、CSV、配列の使い方をよく把握して自分のスキルとしていきましょう!
改行コードの扱い方
改行コードとは
改行コードとはRubyの扱う文字の一つで、文字通り「改行」する文字を表します。
Rubyの文字列表現では”\n”という表現になります。
例えば、
print "hello, jobs!\n"
とあれば、”jobs!”の後で改行して文字が表示されます。
print "hello,\n jobs!\n and tim!\n"
とあれば、”hello,”の後、”jobs!”の後、”tim!”の後で改行して文字が表示されます。
このように、Rubyの文字列の中に改行すべきところをマークするために改行コードが存在します。
“\n”と少し見慣れない表現の文字である改行コードですが、ここできちんと把握されていてください。
改行コードをprintする方法
それでは、実際に改行コードを使用してRubyのプログラムを組んでいきましょう。
ここでは、Rubyの関数「p」と「print」を使ってみます。
なお、「p」は変数の内容を表示した後、自動的に改行します。
「print」は変数の内容を表示し、改行は行いません。
そのため、「print」を使った場合はプログラムを組む人が明示的に「改行コード」を指定しないと改行されません。
# p は改行して出力する p "hello" # print は明示的に改行コード"\n"を文字列に入れないといけない print "hello\n" # 他の文字に紛れていても、"\n"は正しく認識される print "hello\nand\nhello,again\n"
実行結果:
"hello" hello hello and hello,again
以上のように、「p」は文字列の内容を表示た後、自動的に改行しています。
「print」は文字列の中に明示的に”\n”を入れておかないと、改行しません。
2番目の「print」の出力例のように、”\n”と他のアルファベットが混在していても、Rubyはきちんと”\n”を見分けて指定された位置で改行しています。
なお、画面に出力するpやprintについて、詳しくは下記の記事を参照してください。
改行コードをchompで取り除く方法
改行コード”\n”は、文字列の中で改行する位置を指定でき便利です。
しかし、改行コードが余計な場合もあります。
例えば、文字列の中身のデータだけが必要で改行コードが不要な場合です。
そういった場合に、文字列から改行コードを取り除くメソッド「chomp」があります。
「chomp」は文字列の一番最後の改行コードを取り除きます。
また、一番最後に改行コードがなかった場合は何もしません。
つまり、とりあえず「chomp」さえ実行しておけば、文字列の最後に改行コードがある/ないにかかわらず、改行コードが取り除かれた文字列に変換できます。
# chompは文字列の最後の改行コードを取り除く print "hello\n".chomp # あくまで最後の改行コードしか取り除かない print "hello\nand\nhello,again\n".chomp
実行結果:
hellohello and hello,again
以上の実行結果を見るとわかるように、「chomp」は文字列の一番最後の改行コードを取り除きます。
しかし、文字列の途中の改行コードは取り除きません。
これは、もともと「chomp」の用途が、ファイルから1行ずつテキストを読み込んだ際、1行の最後の改行コードを削除して行を標準化して利用する目的のために存在していたためです。
文字列内のすべての改行コードを取り除きたい場合は、次章で述べる「gsub」を使用します。
なお、改行コードを取り除くchompについて、詳しくは下記の記事を参照してください。
改行コードをgsubで取り除く方法
「chomp」は文字列の最後の改行コードしか取り除きませんでした。
「gsub」は文字列内のすべての改行コードを取り除くことができます。
「gsub」は正確には「置換」コマンドで、文字”\n”を空文字””に置換することで、文字列内のすべての改行コードを削除します。
# gsubは文字列のすべての改行コードを取り除く print "hello\n".gsub("\n","") print "\n" # gsubは文字列のすべての改行コードを取り除く print "hello\nand\nhello,again\n".gsub("\n","") print "\n" # 正規表現/\s/は改行コード、半角スペース、タブコードにマッチする print " hello, \n again and \n I miss you long time ago.\n \n".gsub(/\s/,"") print "\n"
実行結果:
hello helloandhello,again hello,againandImissyoulongtimeago.
以上のように、「gsub」に改行コード"\n"を空文字""に置換するように指定すると、文字列内のすべての改行コードが削除されます。
また、「gsub」には正規表現を指定することもできます。
上記例では、/\s/という正規表現を「gsub」に指定し、/\s/にマッチする文字をすべて空文字""に置換し削除しています。
/\s/は、半角スペース、タブ、改行コードにマッチする正規表現です。これらがすべて削除されます。
そのため、上記の実行結果の最後の行のような実行結果になっています。
正規表現に関する基礎知識は以下を参考にしてください。
改行コード付きのファイルを入力する方法
入力から改行コードを取り除いて文字列にする
Rubyでテキストファイルを読み込むと1行ごとに改行コードがついて読み込まれます。
そこで「chomp」で改行コードを取り除いてファイルの内容をRubyの文字列変数に格納してみましょう。
サンプルコードは以下のようです。
# 出力するテキストを保存する変数 text = "" # some_text.txt を読み込むj File.open('./some_text.txt', 'r') do |file| # 1行ごとに読み込む file.each_line do |line| # some_text.txt の各行から改行コードを取り除いて保存 text = text + line.chomp end end # 取得したテキストを出力 print text
なお、Rubyのコードと同じフォルダにsome_text.txtというファイル名で以下のテキストを用意してください。
I want to see you again! Next time, have fun. We have a connection each other!
実行結果:
I want to see you again!Next time, have fun.We have a connection each other!
以上のように、テキストファイル「some_text.txt」から各行を読み込んで、改行コードを削除しRubyの文字列変数に格納できました。
基本的なファイルの読み書きの方法は以下の記事にまとめられているので、参考にしてください。
入力から改行コードを取り除いて配列にする
先ほどは、テキストファイルから改行を取り除いてRubyの文字列にテキストを格納しました。
今度はRubyの配列にテキストを格納してみましょう。
まず、「File」クラスの「read」でテキストファイルの内容をすべて読み込み、そのテキストを「split」で改行コード”\n”で分割します。
「spit」による分割結果は配列になります。
# some_text.txt のテキストをすべて読み込むj file = File.open('./some_text.txt', 'r') contents = file.read # some_text.txt のテキストを改行コードで分割し配列にする ary = contents.split("\n") # 取得した配列を確認表示 p ary
なお、Rubyのコードと同じフォルダにsome_text.txtというファイル名で以下のテキストを用意してください。
I want to see you again! Next time, have fun. We have a connection each other!
実行結果:
["I want to see you again!", "Next time, have fun.", "We have a connection each other!"]
以上のように、テキストファイルの内容を「split」を使って"\n”で分割し、配列として変数「ary」に格納しています。
配列の各要素は、テキストファイルの各行になっていますね。
なお、文字列を分割するsplitについて、詳しくは下記の記事を参照してください。
改行コード付きでファイルへ出力する方法
配列を標準出力に出力する方法
Rubyの配列を1要素あたり1行で標準出力に出力してみましょう。
配列を1要素ごとに出力するには「each」でループし、1回のループごとに要素を出力します。
出力には「p」を使用します。
「p」は自動的に改行するため、「print」のように改行コードをつける必要はありません。
皆さんも以下のコードの「p」を「print」に変えて実行してみて改造してみてください。
# 出力する配列 hairetsu = [1, 2, 3, 4, 5, "6th", "7th", "8th", :nine] # 配列を1行ごとに表示 hairetsu.each{|num| p num }
実行結果:
1 2 3 4 5 "6th" "7th" "8th" :nine
以上のように、配列のすべての要素を1行あたり1要素ごとに「p」で出力しました。
改行コード付きでCSVとして出力する方法
より実践的な例として、改行コード付きでCSVとして出力する方法を解説します。
サンプルコードでは、まず、csv_dataというデータの2次元配列を定義しています。
その後、”sample.csv”ファイルを開き、csv_dataを「each」で1行ごとのデータでループしています。
csv_dataは2次元配列ですので、1行ごとのデータ内に各列のデータが配列として格納されています。
そこで再び「each」を使ってループしています。
最後に、1列ごとにカンマ”,”で区切ってデータをファイルに出力しています。
最後の列を出力後は行の最後になりますので、改行コードをファイルに出力しています。
# 出力する配列 csv_data = [ [ "商品コード", "商品名", "単価" ], [ "AAA-001", "アップル", "10000円" ], [ "BBB-001", "バナナ", "1200円" ], [ "CCC-001", "ケーキ", "8000円" ], ] # 配列をCSV形式でファイルに出力 File.open("sample.csv","w") do |f| # データをループ csv_data.each{ |lineArray| # 1行ごとに実行 lineArray.each{|i| # 1行内のデータを出力 f.print(i) f.print(",") } # 行末に改行コードを出力 f.print "\n" } end
実行結果:
商品コード,商品名,単価, AAA-001,アップル,10,000円, BBB-001,バナナ,1,200円, CCC-001,ケーキ,8,000円,
以上のように、2次元配列csv_dataを行と列の2次元のCSVデータとしてファイルに出力しています。
カンマ”,”と改行コードを出力する箇所を間違わないように気を付けてください。
CSVライブラリでファイルを読み込む方法
RubyにはCSVデータを簡単に扱えるCSVライブラリが存在します。
CSVライブラリを使用するには、コードの頭の方で以下のように宣言します。
require 'csv'
すると「CSV」クラスが使用できるようになるので「foreach」を使ってCSVの行ごとにループします。
CSVの行ごとのループ中では、ブロックの引数にCSVの1行のカンマ区切りのデータが配列に変換されて代入されています。
あとは、配列の「each」を使ってCSVのカンマ区切りのデータを列ごとに取り出すだけです。
実際のサンプルコードをみていきましょう。
# csvライブラリを読み込む require 'csv' # CSVクラスのforeachメソッドで、CSVファイルを1行ごと読み込む CSV.foreach("sample.csv") do |lineAry| # CSVの1行データは配列として取得している p lineAry # 配列として読み込まれているのでeachメソッドを使う lineAry.each do |item| # CSVの個別データを出力する puts item end end
なお、Rubyのコードと同じフォルダにsample.csvというファイル名で以下のテキストを用意してください。
商品コード,商品名,単価, AAA-001,アップル,10000円, BBB-001,バナナ,1200円, CCC-001,ケーキ,8000円,
実行結果:
["商品コード", "商品名", "単価", nil] 商品コード 商品名 単価 ["AAA-001", "アップル", "10000円", nil] AAA-001 アップル 10000円 ["BBB-001", "バナナ", "1200円", nil] BBB-001 バナナ 1200円 ["CCC-001", "ケーキ", "8000円", nil] CCC-001 ケーキ 8000円
以上のように、行ごとの配列「lineAry」を「p」で表示した内容と、列ごとの値「item」を「puts」で表示した内容が一致しています。
このようにCSVライブラリを使用すると、CSVファイルからスマートにデータを取得できます。
CSVライブラリでファイルへ書き込む方法
今度はCSVライブラリを使って、CSVデータをファイルに出力してみましょう。
前章と同じく「CSV」クラスを使い、「CSV」クラスの「open」を使います。
「open」のブロック変数「csv」に「<<」を使ってCSVデータを流し込むだけで、自動的にカンマ区切りのCSVファイルとして出力されます。
コードをみると、非常に簡潔なコードになっていることがわかります。
require 'csv' csv_data = [ [ "商品コード", "商品名", "単価" ], [ "AAA-001", "アップル", "10000円" ], [ "BBB-001", "バナナ", "1200円" ], [ "CCC-001", "ケーキ", "8000円" ], ] CSV.open("items.csv","wb") do |csv| csv_data.each do |csvArray| csv << csvArray end end
実行結果(items.csv):
商品コード,商品名,単価 AAA-001,アップル,10000円 BBB-001,バナナ,1200円 CCC-001,ケーキ,8000円
以上にように、2次元配列csv_dataの「each」でループを回しています。
その後、1次元配列となっている「each」のブロック変数「csvArray」を、配列のまま「CSV」クラスの「open」のブロック引数「csv」に「<<」で出力しています。
このようにCSVライブラリは利便性高く利用できます。
まとめ
今回は、Rubyの改行コード、CSV、配列について学習しました!
学習のポイントを振り返ってみましょう!
- 改行コードを出力できる
- 改行コードを取り除くことができる
- 改行コード付きのファイルを入力・出力できる
- CSVとして入力・出力できる
以上の内容を再確認し、ぜひ自分のプログラムに生かし学習を進めてください!