regexp 符合「包含換行的所有字元」

###Regexp to match “any character including newline (\n)” ?
因為這個蠻常忘記所以記下來。

即使是用 regexp 抓文件中的 <title>...</title> 這麼單純的事情,還是會遇到例外,像是 http://code.google.com/p/ergoemacs/source/browse/packages/xfrp_find_replace_pairs.el 這個頁面的<title>...</title>被很神經病地加上了好幾行換行,如果只寫 <title>.*</title> 就會抓不到。因為 regexp 是以「行」為處理單位,所以寫.*只能抓到「一行裡的所有東西」。

Javascript regexp 抓多行的方法是:

1
"(.|\n)*?"

Emacs regexp 大同小異,除了那多到爆炸的反斜線以外:

1
"\\(?:.\\|\n\\)*?"

說明(以 Emacs regexp 為例,JS 版差不多。)

  • \\(PATTERN\\) 表示一個 group
  • 夾在它中間的\\|表示 or
  • 所以\\(.\\|\n\\)表示「任何字元或\n」
  • \\(?:PATTERN\\)是 group 的一種特殊形式(我不知道其他語言中的 regexp 是否有這種東西),叫做”shy group”。他是一個 group,但是不會被 match-string 抓到,也就是說當你只是要「純粹使用 group」而不需要「用 match-string 抓 group 內的資料」的話,就可以使用這個。
  • 最結尾的 ? 表示 “non-greedy”,只抓最小符合結果。因為 regexp 的設計都是會抓「最長的符合結果」,可以試試看把這裡的 ? 去掉,他會一路抓到檔尾。通常我們要抓多行應該都是希望他抓最小符合結果。

我自己目前是用這個方法,但每次寫都覺得這根本是巫術…不過在 Emacs Wiki 上面還有看到 Emacs regexp 有一個更黑魔法的方法:

1
"[\0-\377[:nonascii:]]*?"

這個我就不懂為何可以表示「包含換行的所有字元」了…不過看起來反斜線比較少比較乾淨 XD。

更多詳情請看 Regexps - GNU Emacs Manual 和第二頁Regexp Backslash,裡面有完整的 Emacs Regexp 列表。


[2014-01-06 月 02:28] 發神經不睡覺貼這個而且等下還要去澆水…。從 url 那篇先提早抽出來寫,不然一篇太長太囉唆。
[2014-01-06 月 18:06] 補上看起正常一點的