sci

最果て風呂

おもろいエスケープ

StackOverflow で質問されていたもの。

Python3 での後方参照がうまくいかなくて、少しだけ悩みました。マニュアルによると、グルーピングしたものは \1 等で参照できるハズなのに、思ったような結果にならないのです。\\1 のようにしないといけないのですわ。

import re
msg = "辞書登録:ドラえもん_クレヨンしんちゃん"
print(re.sub('辞書登録:(.*)_(.*)', '{\n  \\1: \\2\n}', msg))

Ruby でも同じ。実はかつてこちらで使ったことがあったので「バックスラッシュを重複させる」ことについて、頭の片隅に残っていたのです。あらためてリファレンスを見てみると、正規表現内ではキャプチャと呼ぶそうですね(後方参照と呼ぶのは間違いかも)。$1 等は正規表現の処理が終ってからじゃないと使えないみたい。

msg = "辞書登録:ドラえもん_クレヨンしんちゃん"
puts msg.sub(/辞書登録:(.*)_(.*)/, "{\n  \\1: \\2\n}")

マニュアルと実際とが違っていて、わたしはひどく混乱していてる。でも Emacs Lisp はもっとひどくて、\ を表現するために \\ とか \\\\ ってしなきゃいけないんだよね。

(insert (replace-regexp-in-string "辞書登録:\\(.*\\)_\\(.*\\)"
                                  "{\n  \"\\1\": \"\\2\" \n}"
                                  "辞書登録:ドラえもん_クレヨンしんちゃん"))
                                                                            ^
                                                            ここで C-x C-e じゃ!

\ の数を変えて実験してみよう!

(replace-regexp-in-string "\\\\" ;'\\\\' で '\' の意味
                          "\"
                          "バックスラッシュ(\\)を全角へ!") ;'\\' で '\' の意味

ちなみに Vim だとこうかな?

:echo substitute("辞書登録:ドラえもん_クレヨンしんちゃん", '辞書登録:\(.*\)_\(.*\)', "{\n  \"\\1\": \"\\2\"\n}", "")

もしくはバッファに「辞書登録:ドラえもん_クレヨンしんちゃん」を入力しておき、コマンドモードで

:%s/辞書登録:\(.*\)_\(.*\)/{\r  \"\1\": \"\2\"\r}/

あれ?後で参照する方、バックスラッシュの数が減ってません?それと大多数の言語では \n を使うのに \r だし。