Ruby入門(3.文字列操作とIO)です。
たのしいRuby 第5版を参考にしています。
文字列は"~"あるいは'~'で作る。'~'でくくった場合は、変数名や#{}による式展開を行わず、\nなどの特殊文字も変換しない。
文字列は変数に格納でき、メソッドの引数に渡すことができる。文字列は配列との共通点が多く、さまざまな配列に用いる操作を使うことができる。
また、Rubyでは+で文字列をつなげたり、==や!=で比較できる。大小比較をすると文字コードの順番に決まる。
文字列の長さは、lengthメソッドやsizeメソッドを使って得られる。
バイト数を得たい時はbytesizeメソッドを使う。
また、empty?メソッドで、文字列の長さが0かそうでないかを調べられる。
改行文字はchompやchomp!で削ることができる。
s_hoge = "Hoge\nFuga\nFoo\nBar\n" s_hoge.each_line do |line| line.chomp! print line print ':' end
文字列の全ての行に対する操作は、.each_lineメソッドにブロックを渡すことで実現できる。
s_hoge = "Hoge\nFuga\nFoo\nBar\n" s_hoge.each_line {|line| print line }
.lines.to_aを使えば、文字列を配列に変換できる。
s_hoge = "Hoge\nFuga\nFoo\nBar\n" a_hoge = s_hoge.lines.to_a a_hoge.each {|item| item.chomp! } p a_hoge #=> ["Hoge", "Fuga", "Foo", "Bar"]
"や'を含む文字列:
s_hoge = %Q{「''」だろうが「""」だろうがなんでもあり。} s_assy = %q|Assy said, "How are you, Schwarz?", and Schwarz said, "I'm good, Thank you."|
また、Perl風のヒアドキュメントを使うこともできる。
print(<<"EOB") Assy makes a robot, called "Schwarz". It will be the next life on the universe. EOB
EOBの位置がインデントを醜くさせると思うなら、<<ではなく<<-を使えば、EOBの前にある空白やタブが無視される。
文字列はsplitメソッドで指定した文字(以下の例では:)で分割できる。
s_inoue = "井上:茜:女性:20歳:大学生" a_inoue = s_inoue.split(/:/) p a_inoue #=> ["井上", "茜", "女性", "20歳", "大学生"]
文字列を検索するには、indexあるいはrindexを使う。
indexは左から、rindexは右から文字列を検索し、見つかった場合は先頭部分のインデックスを、見つからなかった場合はnilを返す。
s_hoge = "hoge is an animal." p s_hoge.index("hoge") #=> 0
含まれているかどうかだけを調べたいならinclude?メソッドを使う。
置換はsubメソッドとgsubメソッドを使う。
また、trメソッドを使うことでも文字列を置換できる。UNIXのtrコマンドと同様に、"a-z"を"A-Z"のように文字をまとめて指定して置換できる。
`コマンド`はコマンド置換と呼ばれ、コマンドを実行してその実行結果として出力された文字列を得ることができる。
irb(対話型のRubyプロンプト)などで使うと便利である。
Rubyスクリプト自体のエンコーディングは、以下のようにスクリプトの最初の行あるいは#! ~で始まる際には二番目の行に記述する。これをマジックコメントという。
# encoding: utf-8
また、Emacsやvimと共通化できるように、
# -*- coding: utf-8 -*- # vim:set fileencoding=utf-8:
などでも指定できる。
エンコーディングには、スクリプトエンコーディング、内部エンコーディング、外部エンコーディングがある。
エンコーディング | 説明 |
---|---|
スクリプトエンコーディング | Rubyスクリプトのエンコーディング。 |
内部エンコーディング | 外部から入力して受け取ったデータのエンコーディング。 |
外部エンコーディング | 外部に出力として吐き出すデータのエンコーディング。 |
エンコーディングの基本はEncodingクラス。エンコーディングの互換性を調べたり、デフォルトの外部・内部エンコーディングを調べたりできる。
デジタル情報も参照のこと。
文字列の文字コード変換はString#encodeメソッドあるいはString#encode!メソッドを使う。
# encoding: EUC-JP euc_str = "ほげほげ" utf8_str = euc_str.encode("utf-8")
文字列のエンコーディングを調べるにはString#encodingメソッドを使う。
IOオブジェクトを使って入出力を行う時にエンコーディング処理を行うには、IO#external_encoding(外部エンコーディング)、IO#internal_encoding(内部エンコーディング)、IO#set_encoding(エンコーディングをIOに指定)を使う。
以下はIO#set_encodingメソッドを使ったエンコーディング設定の例。エンコーディングは"外部エンコーディング:内部エンコーディング"の形式の文字列を指定する。
$stdin.set_encoding("EUC-JP: UTF-8");
RubyではPerlライクな正規表現を使うことが可能です。
マッチした文字列は、自動で$1などの変数に格納される。()を使った場合、マッチ部分が複数ある時は$1, $2, $3などとなる(キャプチャ)。たとえば、
s_hoge = "hooooooge fuuuga" /ho*ge/ =~ s_hoge print "マッチした部分: ", $1, "\n"
if文で使う場合:
if /ho*ge/ =~ s_hoge # マッチした場合に行う処理 else # マッチしなかった場合に行う処理 end
正規表現については正規表現のページを参照のこと。
以下は最初にマッチした部分だけを置換するsubメソッドと、マッチする全ての部分を置換するgsubメソッド。
str = "わたしは猫のクロ。真っ黒な猫だ。" p str.sub(/クロ/, 'ゴンタ') #=> "わたしは猫のゴンタ。真っ黒な猫だ。" p str.gsub(/猫/, '犬') #=> "わたしは犬のクロ。真っ黒な犬だ。"
scanメソッドはgsubメソッドと同様、パターンにマッチした部分を取り出す。gsubメソッドと違い、置換はせず、取り出すだけを行う。
プログラムを起動すると、標準入力、標準出力、標準エラー出力の3つが割り当てられる。
標準入力は、端末からキー入力を受け取る。組み込み定数はSTDIN、グローバル変数は$stdin。レシーバを指定せずにgetsなどのメソッドを実行した場合、標準入力から入力する。
$stdin.each_line do |line| # lineに対する処理をここに書く end
標準出力は、端末に文字を出力する。組み込み定数はSTDOUT、グローバル変数は$stdout。レシーバを指定せずにputs, print, printfなどのメソッドを実行した場合、標準出力に文字を表示する。
$stdout.puts "assy", "schwarz", "zaidou"
また、標準エラー出力の組み込み定数はSTDERR、グローバル変数は$stderr。
ファイルの入出力は、IOクラスを継承した派生クラスのFileクラスで行える。
File.open("hoge.txt") do |file| file.each_line do |line| # lineに対する処理をここに書く end end
このように書くことも出来ます。
File.open("hoge.txt") do |io| while line = io.gets # lineに対する処理をここに書く end end
Rubyではブロックを使うことで直感的なコードを書くことが出来ます。
ファイルを開いて新しいIOオブジェクトを得るには、
io = File.open(file, mode)
あるいは
io = open(file, mode)
とする。
モードには、"r", "r+", "w", "w+", "a", "a+"を指定する。
通常は読み込み専用ならr、書き込み専用ならw、追記ならaを指定する。読み込みと書き込みを両用する場合にはr+を指定する。wやw+を指定すると、既にファイルが存在する場合に内容を消去する。
その他のAPIは以下のようになる。
API | 記法 |
---|---|
io.close | ファイルを閉じる。 |
io.closed? | 閉じられたかどうかを調べる。 |
File.read | ファイルを一気に全て読み込む。 |
io.gets io.each io.each_line io.readlines | 1行読み込む。 |
io.lineno | 行ごとに読み込んだ際に記録される「今どれだけ読み込んだか」の記録を取得する。 |
io.getc | 一文字ずつ読み込む。 |
io.ungetc | 読み込みを一文字元に戻す。 |
io.read | サイズを指定して読み込む。 |
io.each_char | 読み込んだ文字に一文字ずつブロックの処理をかける。 |
io.print | 文字列を出力する。 |
io.puts | 改行文字を加えて出力する。 |
io.printf | 書式を指定して出力する。 |
io.write io << str | これらを使ってでも文字列を出力できる。 |
C言語と同様にsprintfメソッドを使うことで、出力せずにフォーマット指定だけをして、変数などを書式指定した文字列に変換できる。
Linuxシステムコール・APIも参照のこと。