【Ruby】文字列クラス
- 作者: 高橋征義,後藤裕蔵,まつもとゆきひろ
- 出版社/メーカー: ソフトバンククリエイティブ
- 発売日: 2013/06/04
- メディア: 単行本
- この商品を含むブログ (22件) を見る
今回は第14章「文字列(String)クラス」
Ruby での「文字列」はすべて String クラスのオブジェクトである。
String クラスの扱いについて掘り下げていく。
- 文字列を作る
- 文字列の長さを得る
- 文字列のインデックス
- 文字列の連結と分割
- 文字列を比較する
- 改行文字の扱い方
- 文字列の検索と置換
- 文字列と配列で共通するメソッド
- 日本語文字コードの変換
文字列を作る
str1 = "これも文字列" str2 = 'あれも文字列' puts "#{str1}です" #=> これも文字列です puts '#{str2}です' #=> #{str2}です
改行(\n)など、\ を使った特殊文字は次の通りである。
特殊文字 | 意味 |
---|---|
\t | タブ(0x09) |
\n | 改行(0x0a) |
\r | 復帰(0x0d) |
\f | 改ページ(0x0c) |
\b | バックスペース(0x08) |
\a | ベル(0x07) |
\e | エスケープ(0x1b) |
\s | 空白(0x20) |
\v | 垂直タブ(0x0b) |
\nnn | 8進数表記(n = 0~7) |
\Xnn | 16進数表記(n = 0~9, a(A)~f(F) |
\cx, \C-x | [Control] + x |
\M-x | [Meta]([Alt]) + x |
\M-\C-x | [Meta]([Alt]) + [Control] + x |
\x | 文字xそのもの(xは上の文字以外) |
\unnnn | Unicode 文字の16進数表記(n = 0~9, a(A)~f(F) |
%Q,%q
「"」「'」を含んだ文字列を作りたいときに便利である。
puts %Q{Rubyの文字列には「''」も「""」も使われます。} #=> Rubyの文字列には「''」も「""」も使われます。 puts %q{Ruby said, 'Hello world!'} #=> Ruby said, 'Hello world!' puts %Q{Ruby\nsaid,\n"Hello!"} #=>Ruby #=>said, #=>"Hello!" puts %q{Ruby\nsaid,\n"Hello!"} #=> Ruby\nsaid,\n"Hello!"
ヒアドキュメントを使う
<< を使って文字列を作るというもの。
<< "終了の記号" 置き換える文字列 終了の記号
という形で使う。終了の記号には「""」か「''」で囲った文字列を書く(どちらもない文字列が使われ場合は「""」で囲った文字列と見なされる)。
10.times do |i| 10.times do |j| print(<<"EOB") i: #{i} j: #{j} i*j = #{i*j} EOB end end
ヒアドキュメントの終わりに書く文字列は行頭になければならない。インデントを揃えたい場合は、「<<-」を使う。これを使うと、行頭側の空白文字、タブ文字が無視される。
# インデントを揃える 10.times do |i| 10.times do |j| print(<<-"EOB") i: #{i} j: #{j} i*j = #{i*j} EOB end end
# 変数に代入 str = <<-EOB Hello! Hello! Hello! EOB puts str
printf, sprintf
文字列クラスのメソッドではないが、決められたフォーマットで文字列を出力するためのメソッドである。
n = 123 printf("%d\n", n)
最初の引数が与えられたデータをどのような形で出力するかを指定するフォーマットで、2つ目以降の引数がそのフォーマットの中の「%」のある位置に、順に埋め込まれる。
n = 123 m = 456 printf("%d%d\n", n, m) #=> 123456 printf("%d\n", n, m) #=> 123 printf("%d\n%d\n", n) #=> (ArgumentError)
「%」と「d」の間に文字を加えて、さらなる指定をすることができる。
n = 123 printf("%4d\n", n) # 4桁で出力 printf("%04d\n", n) # 指定した桁数に満たない場合は先頭を0で埋める printf("%+d\n", n) # 「+」か「-」の記号を必ず出力
出力結果は次のようになる。
123 123 0123 +123
「d」は整数を出力するための指定用文字で、他にも引数を文字列として解釈させるための指定「s」もある。
n = "Ruby" printf("%s\n", n) printf("Hello,%s!\n", n) printf("Hello,%8s!\n", n) # "Ruby"を8桁で出力 printf("Hello,%-8s!\n", n) # 8桁で、左詰めで出力
出力結果はこうなる。
Ruby Hello,Ruby! Hello, Ruby! Hello,Ruby !
出力と同様の結果を文字列オブジェクトとして生成するためのメソッドが sprintf である。
p sprintf("%d", 123) #=> "123" p sprintf("%4d", 123) #=> " 123" p sprintf("Hello,%s!","Ruby") #=> "Hello,Ruby!"
文字列の長さを得る
length, size
# 文字列の長さを返す p "just another ruby hacker,".length #=> 25 p "just another ruby hacker,".size #=> 25 p "みなさん、こんにちは。".size #=> 11
bytesize
# バイトの長さを返す p "みなさん、こんにちは。".bytesize #=> 22
empty?
# 文字列の長さが0なら真を返す p "".empty? #=> true p "foo".empty? #=> false
文字列のインデックス
puts str[0] #=> あ puts str[9] #=> こ puts str[-1] #=> こ puts str[5..9] #=> かきくけこ puts str[0, 5] #=> あいうえお
文字列をつなげる
文字列をつなげるには、
- 2つの文字列がつながった文字列を新しく作る
- 既にある文字列に別の文字列をつなげる
の2つの方法がある。
# 新しい文字列を作る hello = "Hello," world = "world!" str = hello + world p str #=> "Hello,world!"
# 既にある文字列に別の文字列をつなげる hello = "Hello," world = "world!" hello << world p hello #=> "Hello,world!" hello.concat(world) p hello #=> "Hello,world!world!"
「+」をつかって表現もできる。
hello = "Hello," world = "World!" hello = hello + world p hello #=> "Hello,world!"
<< メソッドなどを使うと同じオブジェクトを指す別の変数にも影響がある一方、「+」を使った場合にはそれがない。
hello = "Hello," world = "world!" str = hello hello = hello + world p hello #=> "Hello,world!" p str #=> "Hello," hello = "Hello," world = "world!" str = hello hello << world p hello #=> "Hello,world!" p str #=> "Hello,world!"
文字列を比較する
「==」や「!=」を使って比較できる。
p "aaa" == "aaa" #=> true p "aaa" == "aa" #=> false p "aaa" != "aa" #=> true p "aaa" != "aaa" #=> false
文字列を分割
# 「:」で区切られたそれぞれの文字列を要素とする配列を代入 str = "高橋:タカハシ:25:000-111-000" column = str.split(/:/) p column #=> ["高橋", "タカハシ", "25", "000-111-000"]
改行文字の扱い方
each_line などで文字列を読み込んだ場合は末尾に改行文字がつくが、この改行文字が邪魔な場合に改行文字を取り除くメソッドがある。
末尾を必ず1文字削る | 改行がある場合のみ削る | |
---|---|---|
非破壊的 | chop | chomp |
破壊的 | chop! | chomp! |
# 末尾が改行文字でない str = "abcde" newstr = str.chop p newstr #=> "abcd" newstr = str.chomp p newstr #=> "abcde" # 末尾が改行文字 str = "abcde\n" newstr = str.chop p newstr #=> "abcde" newstr = str.chomp p newstr #=> "abcde"
each_line メソッドを使う場合には chomp! メソッドなどで破壊的に改行文字を落とすのが常套である。
f.each_line do |line| line.chomp! line を処理する end
文字列の検索
文字列の検索
文字列の中に特定の文字列が含まれているかどうかを調べるときは index, もしくは rindex メソッドを使う。rindex の r は right(右) の r。
str = "すももももも" p str.index("もも") #=> 1 p str.rindex("もも") #=> 4 # 見つかった場合は一致部分の先頭のインデックスを返す p str.index("みかん") #=> nil
# 単純に含まれているかいないかの判別 str = "すももももも" p str.include?("もも") #=> true p str.include?("みかん") #=> false
文字列と配列で共通するメソッド
インデックス操作に関するメソッド
str = "abcde" str[2] = "C" p str #=> "abCde" str[1,3] = "BCD" p str #=> "aBCDe"
slice!
p str.slice!(-1) #=> "." p str.slice!(5, 1) #=> "," p str.slice!(0..4) #=> "Hello" p str #=> "Ruby"
Enumerator オブジェクトを返すメソッド
# each_line メソッドで取り出した行を collect メソッドで処理 str = "あ\nい\nう\n" tmp = str.each_line.collect do |line| line.chomp * 3 end p tmp #=> ["あああ", "いいい", "ううう"] # each_byte メソッドで取り出した数値を collect メソッドで処理 str = "abcde" tmp = str.each_byte.collect do |byte| -byte end p tmp #=> [-97, -98, -99, -100, -101]
連結や逆順に関するメソッド
concat
s = "ようこそ" s.concat("ゲストさん") puts s #=> ようこそゲストさん
delete
s = "検/索/避/け"
puts s.delete("/") #=> 検索避け
|
reverse
s = "こんばんわ" puts s.reverse #=> わんばんこ
その他のメソッド
strip
# 先頭と末尾の空白文字を剥ぎ取る p " Thank you. " #=> " Thank you. " p " Thank you. ".strip #=> "Thank you."
** case, capitalize
case というのは、ここではアルファベットの大文字・小文字の意味。
p "Thank you, Ruby.".upcase #=> "THANK YOU, RUBY." p "Thank you, Ruby.".downcase #=> "thank you, ruby." p "Thank you, Ruby.".swapcase #=> "tHANK YOU, rUbY." p "Thank you, Ruby.".capitalize #=> "Thank you, ruby." # 先頭の文字を大文字に、以降の文字を小文字にする
tr
p "ABCDE".tr("A", "a") #=> "aBCDE" p "ABCDE".tr("ADE", "ade") #=> "aBCde" p "ABCDE".tr("A-E", "a-e") #=> "abcde"
日本語文字コードの変換
encode
# encoding: EUC-JP euc_str = "日本語EUCの文字列" utf8_str = euc_str.encode("utf-8")
encode メソッドで指定できる文字コードの一覧は Encoding.name_list メソッドで取得できる。
nkf ライブラリ
半角カナを全角カナに変換するといった用途に使われる。
nfk メソッドの主なオプションは次の通りである。
オプション | 意味 |
---|---|
-d | 改行文字からCRを削除する |
-c | 改行文字にCRを加える |
-x | 半角カナを全角カナに変換しない |
-m0 | MIME の処理を抑制する |
-h1 | カタカナをひらがなにする |
-h2 | ひらがなをカタカナにする |
-h3 | ひらがなとカタカナを入れ替える |
-Z0 | JIS X 0208 の数字を ASCII にする |
-Z1 | -Z0 に加えて全角スペースを半角スペースにする |
-Z2 | -Z0 に加えて全角スペースを半角スペース2個にする |
-e | 出力文字コードを EUC-JP とする |
-s | 出力文字コードを Shift_JIS とする |
-j | 出力文字コードを ISO-2022-JP とする |
-w | 出力文字コードを UTF-8(BOM なし)とする |
-w | 出力文字コードを UTF-8(BOM あり)とする |
-w80 | 出力文字コードを UTF-8(BOM なし)とする |
-w16 | 出力文字コードを UTF-16(Big Endian / BOM なし)とする |
-w16B | 出力文字コードを UTF-16(Big Endian / BOM あり)とする |
-w16B0 | 出力文字コードを UTF-16(Big Endian / BOM なし)とする |
-w16L | 出力文字コードを UTF-16(Little Endian / BOM あり)とする |
-w16L0 | 出力文字コードを UTF-16(Little Endian / BOM なし)とする |
-E | 入力文字コードを EUC-JP とする |
-S | 入力文字コードを Shift_JIS とする |
-J | 入力文字コードを ISO-2022-JP とする |
-W | 入力文字コードを UTF-8(BOM なし)とする |
-W8 | 入力文字コードを UTF-8(BOM あり)とする |
-W80 | 入力文字コードを UTF-8(BOM なし)とする |
-W16 | 入力文字コードを UTF-16(Big Endian / BOM なし)とする |
-W16B | 入力文字コードを UTF-16(Big Endian / BOM あり)とする |
-W16B0 | 入力文字コードを UTF-16(Big Endian / BOM なし)とする |
-W16L | 入力文字コードを UTF-16(Little Endian / BOM あり)とする |
-W16L0 | 入力文字コードを UTF-16(Little Endian / BOM なし)とする |
トラブルを避けるため、単純に文字コードを変換することが目的の場合は -x と -m0(まとめて -xm0 と書ける)を常に指定すべきである。
# encoding: EUC-JP require "nkf" euc_str = "日本語EUCの文字列" utf8_str = NKF.nkf("-E -w -xm0", euc_str)
入力文字コードの指定を明示的に行わない場合はライブラリが自動的に判別を行うため、たいてい次のように書くことが出来る。
# encoding: EUC-JP require "nkf" euc_str = "日本語EUCの文字列" utf8_str = NKF.nkf("-w -xm0", euc_str)
日本語の文字に関する特殊な処理を除けば、 encode メソッドを使うのがよい。