LoginSignup
1

More than 3 years have passed since last update.

rubyで英語翻訳ごっこ!:正規表現で語順の違いを解決してみた

Posted at

gsubメソッドで翻訳ごっこして遊んでみた

Rubyという言語には、文字列をお手軽に変換する「gsub」というメソッドがあります。

fruits.rb
input = "apple"
input.gsub("apple","banana")   #=>"banana"

こんな感じで"apple"を"banana"に変えられます。
gsubメソッドを知ったとき、「これで翻訳できるんとちゃう…?」と思ったのでやってみました。
"I love you" を日本語に翻訳するコードを書いてみます。

love.rb
input = "I love you"
input_1 = input.gsub("I","私は")               #=>"私は love you"
input_2 = input_1.gsub("love","愛してる")    #=>"私は 愛してる you"
input_3 = input_2.gsub("you","あなたを")    #=>"私は 愛してる あなたを"

"I love you" ⇒ 「私は 愛してる あなたを」
語順に違和感がありますが、すべての英語を日本語に変えることができました。
ちなみに、もっとコードを短くしたい場合は

love.rb
input = "I love you"
input.gsub(/I|love|you/, "I"=>"私は","love"=>"愛してる","you"=>"あなたを")
#=>"私は 愛してる あなたを"

と書くこともできます。

さて、ここからが本題です。
違和感があるのは、日本語と英語では語順が違うため。
"I love you"で問題になるのは"love"と"you"の順番が逆
という点です。
汎用性も高めたいですね。"I tell you"や"I beg you"にも同じように対応したい。
つまり、

「何らかの単語」(空白)"you" ⇒ "you" (空白)「何らかの単語」

に置き換えたい。

そこで、
正規表現.png

youの前にある単語を、youの後ろにもってくる」コードを書いてみることにしました。

正規表現のキャプチャを使って語順を入れ替える

結論からいくと、こんなコードで出来ました。(実行環境はirb)

love.rb(追加部分)
input = "I love you"

if input =~ /([A-Za-z]+\s)you/
input.gsub(($1)+"you" , "you\s"+($1))
end                                     

#=>"I you love"

正規表現っていきなり見ると少しびっくりする方もいると思うので(まさに私がそう)、ゆっくり説明しようと思います。

まずinputの文字列のなかから、「何らかの単語があって、そのあとに空白があって、そのあとにyouと書いてある」部分を探します。
そういう部分のことを正規表現で表すと
 /([A-Za-z]+\s)you/ になるのです。
正規表現.png

そして、「()」で括られた部分、([A-Za-z]+\s) は今後、($1)という名前でコード上で取り扱えるようになりました。

さて、if input =~ /([A-Za-z]+\s)you/ という処理によって、"I love you"のなかの"love you"というところが抜き出され、"love(空白)" の部分が($1)として扱えるようになりました。
正規表現.png

あとは、"($1)+you" をgsubメソッドで変換して、 "you+ \s (空白) +($1)" に変形しました。

このコードで love you を you loveに。

love.rb(追加部分)
input.gsub(($1)+"you" , "you\s"+($1))

空白を入れないと "youlove" になってしまい、あとで日本語に変換できなくなってしまいます。空白は"\s"で表現できます。

引っかかった点としては、($1)を「""」で囲むと出力がうまくいかないということです。なので「+」を使って文字列を結合させています。

それでは、「"I love you"を正しい日本語の語順で翻訳する」作業をしてみます。

love.rb(追加部分)
input = "I love you"

if input =~ /([A-Za-z]+\s)you/
input =  input.gsub(($1)+"you" , "you\s"+($1))
end
#=> "I you love "

input.gsub(/I|love|you/, "I"=>"私は","love"=>"愛してる","you"=>"あなたを")
#=> "私は あなたを 愛してる "

語順が正しくなりました!

私は正規表現がとても苦手なのですが、こういう風に遊んでみた結果ちょっとだけ親しめたよ、という話でした。
正規表現ってテキストやってるだけではとっつきにくいことこの上ないので、手を動かしてみると「意外と簡単じゃん」と思えるかもしれません。

最後まで読んでくださった方、ありがとうございました。
間違っているところがあればご指摘ください。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1