文字列は、String クラスに属した値である。文字列に関する様々な処理は Stringクラスに備わっている以下のメソッドで行なうことができる。
+
other - 文字列の結合
元の文字列と別の文字列 other を繋げた文字列を 新たに作りそれを返す。元の文字列は破壊されない。
x="abc" x + "hoge" => "abchoge" x => "abc" (変わらない)
<<
other concat
(other) - 文字列の破壊的追加
元の文字列に別の文字列 other を追加する。 元の文字列自体が破壊的に変更される。
x="abc" x << "hoge" (x.concat("hoge") も同じ) => "abchoge" x => "abchoge" (変わる)
元の文字列を保存する必要がある場合は +
を、
そうでない場合は <<
を利用する。
*
times - 文字列の繰り返し
元の文字列を times 回数だけ繰り返したものを新たに作 り、それを返す。
"-+" * 5
=> "-+-+-+-+-+"
[nth]
- nth番目の文字
元の文字列の nth 番目(0から数える)の文字を返す。
x="ABCabc" x[0] => "A" x[-2] => "b"
添字に負の整数を指定すると、文字列の最後から数える。つまり、-1 が最後の文字で-2が最後から2文字目となる。
[start..last]
- 部分文字列の取り出し(1)
元の文字列の start 番目(0から)の文字から last 番目の文字までの部分文字列を返す。start 番目の文字と、last番目の文字列を両端に含む。
x="abcdefg"
x[2..5]
=> "cdef"
添字に負の整数を指定すると文字列の最後から数える。
x="abcdefg" x[3..-1] => "defg" x[-3..-1] => "efg"
[start, length]
- 部分文字列の取り出し(2)
元の文字列の start 番目(0から)の文字から length 文字分の部分文字列を返す。
x="abcdefg" x[3, 2] => "de" x[4, 1000] => "efg"
chop
chop!
元の文字列の最後の一文字を取り除いたものを返す(最後が
DOS改行 \r\n
なら2文字削除する)。
chop!
は
元の文字列を破壊的に書き変える。
"abc\n".chop => "abc" "abc\r\n".chop => "abc" "abc\n".chop.chop => "ab"
chomp
(rs)chomp
chomp!
(rs)chomp!
- 文字列の末尾削除(条件付)
文字列末尾から調べて rs という文字列があれば
それを取り除く。なければなにもせず、nil
を返す。
rs を指定しない場合は改行文字が取り除か
れる(厳密には変数 $/
の値)。chomp!
は、
元の文字列を破壊的に変更する。
x="abc\n" x.chomp => "abc" x => "abc\n" (変わらない) x="abc" x.chomp => "abc" x="abc\n" x.chomp! => "abc" x => "abc" (変わる)
通常、ファイルや端末から1行ずつ読み込んだ文字列には
末尾に改行文字(\n
)がつくので、
これを取り除きたいときに利用する。
downcase
downcase!
- 文字列の小文字化upcase
upcase!
- 文字列の大文字化capitalize
capitalize!
- 文字列のキャピタライズ
元の文字列のうちアルファベットをすべて 小文字化
(downcase
)、大文字化(upcase
)、または
先頭大文字化(capitalize
)する。
downcase! upcase! capitalize!
は、破壊的に書き変える。
x="Hello, World!!" x.upcase => "HELLO, WORLD!!" x.downcase => "hello, world!!" x.capitalize => "Hello, world!!"
gsub
(pattern){replace}gsub!
(pattern){replace}
- 文字列の置き換え
元の文字列のうち pattern にマッチするものを すべて replace に置き換え、その結果の 文字列を返す。
単純に文字列を置換することもできるし、
x = "This is a pen" y = x.gsub(/is/){"IS"} x => "This is a pen" y => "ThIS IS a pen"
パターンを指定して、マッチするものすべてを置換することもできる。
x = "This is a pen. That is a pencil." x.gsub(/is/){"IS"} (単純な is 指定) => "ThIS IS a pen. That IS a pencil." x.gsub(/\bis\b/){"IS"} (\bは「単語の境界」を意味する正規表現) => "This IS a pen. That IS a pencil."
単語の末尾1字のみ大文字に変えるには以下のようにする。
x = "This is a pen. That is a pencil." x.gsub(/(\w*)(\w)\b/){$1+$2.upcase} => "ThiS iS A peN. ThaT iS A penciL."
パターンの部分 pattern にグルーピングの ( ) を使った場合、
括弧内の正規表現にマッチした部分文字列が自動的に
$1, $2, $3, ...
に保存される。これらは
置き換え文字列 replace で利用でき、
$1
は1個目の( )にマッチした文字列に、
$2
は2個目の( )にマッチした文字列に、
$N
はN個目の( )にマッチした文字列に、
それぞれ置き換えられる。
上記の正規表現では最初の括弧 (\w*)
が最後の1字を除いた英単語で、2個目の括弧
(\w)
が英単語の最後の1字に
マッチする。\b
は単語の境界を意味するのでマッチングは
1単語ごとに行なわれる。
以下の例は、文字列中に現れるすべての `dog' または `cat' を
それぞれ、`pretty dog', `pretty cat' に置き換える。cat, dog が
複数形だった場合にもマッチし (s?
)、
その場合は置換え後の文字列にもsを付ける。
x="I saw cats scattered by a dog."
x.gsub(/\b(dog|cat)(s?)\b/i){'pretty '+$1+$2}
=> "I saw pretty cats scattered by a pretty dog."
置換え後の文字列に $1, $2
を使う場合には
引用符の外に出すように気を付ける。
sub
(pattern){replace}sub!
(pattern){replace}
- 文字列の置き換え
上記 gsub(gsub!)
はパターンにマッチするものすべてを
置き換えるが、sub(sub!)
は最初の一つだけを置き換える。
その他の点はgsub(gsub!)
と同じ。
x = "This is a pen. That is a pencil."
x.sub(/is/){"IS"}
=> "ThIS is a pen. That is a pencil."
length
size
- 文字列の長さ
文字列の長さを返す。
x="abcde"
x.length
=> 5
reverse
reverse!
- 文字列の逆文字列
元の文字列の並びを逆にした文字列を返す。
reverse!
は元の文字列を破壊的に変更する。
x="abcde" x.reverse => "edcba" x => "abcde" x.reverse! => "edcba" x => "edcba"
split
split
(sep) - 文字列の分割
元の文字列を、指定したパターン sep を区切りと 見なして分割し、分割された文字列を配列に格納して返す。sep を省略したときは空白を区切りと見なす(厳密には変数 $; の値で、$; がnil の場合は先頭を除いた空白となる)。
特定の記号(カンマなど)で区切られた文字列を一気に分割して
配列に格納するときに利用する。
join
の逆と思えば良い。たとえば、カンマで区切られた次のような
データがあるとする。
中町太郎, 90, 70,20
各項目が「カンマ(,) スペース(が0個以上)」 で区切られている。
これを正規表現にすると /,\s*/
となるので、
以下のようにすると
この行から項目だけを抽出した配列が生成される。
"中町太郎, 90, 70,20".split(/,\s*/)
=> ["中町太郎", "90", "70", "20"]
これまで何度か登場した成績処理プログラムをsplit
を利用して書き換える場合、データの読み込み部分を以下のように
変更すればよい。
正規表現で分解するバージョン:
point = Hash.new while line=gets if /(\S+)\s+(\d+)\s+(\d+)/ =~ line point[$1] = [$2.to_i, $3.to_i] # 配列を代入 end end
↓
split
で分解するバージョン:
point = Hash.new while line=gets data = line.split(/,\s*/) point[data[0]] = data[1..-1] end