* U K I Y A H O N P O *
Nel mezzo del cammin di nostra vita mi ritrovai per una selva oscura,
che la diritta via era smarrita.
リロード   新規 下位ページ作成 編集 凍結 差分 添付 コピー 名前変更   ホーム 一覧 検索 最終更新 バックアップ リンク元   ヘルプ   最終更新のRSS
浮子屋商店もよろしく。

正規表現講座/おまけ1 のバックアップソース(No.2)

TITLE:間違いだらけの正規表現講座 おまけ 1

#contents

* さくらスクリプトの正規表現 [#zaaa4f74]

さくらスクリプトをなるべく正確に正規表現にするのにチャレンジしてみます。

参考元は http://crow.aqrs.jp/reference/all/ です。


** まずはチャレンジ [#bd72415a]

とりあえず書いてみたもの。

#pre{{
\\(\\|q\[.*?\]\[.*?\]|[!&8fijmpqsn]\[.*?\]|[-*+01456bcehntuvxz]|_[ablmsuvw]\[.*?\]|__(t|w\[.*?\])|_[!?+nqsV]|[wi][0-9])
}}

分解すると

#pre{{
\\                          #\ 記号そのもの
(
  \\|                       #\\(エスケープされた\)
  q\[.*?\]\[.*?\]|          #\q[id][選択肢表示名]
  [!&8fijmpqsn]\[.*?\]|     #\○[~]系
  [-*+01456bcehntuvxz]|     #\○系
  _[ablmsuvw]\[.*?\]|       #\_○[~] 系
  __(t|w\[.*?\])|           #\__○ 系
  _[!?+nqsV]|               #\_○系
  [wi][0-9]                 #\w9と\i9 系
)
}}

これだと、本当は \\ はさくらスクリプトのタグ''ではない''
(表示文字として残さなければならない)ので反則なんですけど。

** 前読みを使ったパターン [#na932591]


\\を残すとして、前読みを使うと冒頭がこうなります。

#pre{{
((?<=\\\\)|(?<!\\))\\(q\[.*?\]~

(
  (?<=\\\\)|    #肯定前読み、\\\w9 のようなパターンに対応
  (?<!\\)       #否定前読み、\\w9 のようなパターンに対応
)
\\
(q\[.*?\]~
}}


ただしこれだと、「\\\\w9」みたいなパターンには対応できないわけです。

さらにもう1個、冒頭の否定肯定を繰り返せば、「\\\\w9」には対応できますが、
それを延々と繰り返すわけにも行かない。

前読みで「偶数個マッチ」「奇数個マッチ」等ができる処理系はあまりないので、
どこかで妥協するしかないのでしょうね。


現実的な解としては、
- \\ をもとの文章中に出てこない適当な文字、たとえばASCIIの0x01とか、に変えておく
- 正規表現を適用する
- さっき変えた 0x01 を \\ に書き戻す

という手順を踏むことによって解決できるのですが。


引っ掛けられなかったり、あるいは誤爆してしまう場合があったら教えてください。

* ご指摘などはこちらへ [#oa19ce6c]

#comment