InDesign CS4の肯定的先読みとOR表現の組み合わせ

[8818]InDesign CS4の肯定的先読みとOR表現の組み合わせ 投稿者:cu39 投稿日:2015/11/12 00:09:25
OS: Windows 7/Mac OS X 10.9.5
Version: InDesign CS4

正規表現検索で、肯定的先読みと論理和(OR)を組み合わせたいのですが、目的の挙動にならず、うまい方法をご存知の方がいたら教えていただきたいと思っています。

文章の中から名詞を複数化する「達」だけを抜き出そうとしました。テスト用に次の文例を使います。

> 私達は発達して上位下達の社会で仲間達へ情報を伝達し、人生の達観を達成した達人など様々な人達とともに物資調達を達成します。

この中から「私達」「仲間達」「人達」(それぞれの「達」のみ)を抜き出せれば目的が果たされたことになります。

(?<!上意下|[調伝到発])達(?![しす観者人成])

Ruby 2.1.5 (正規表現エンジンは onigmo)では上掲の表現でうまくいきます(添付URL参照)。
少しアレンジして以下の表現でも同じ結果が得られます。

(?<![調伝到発]|上意下)達(?![しす観者人成])
(?<!上意下|調|伝|到|発)達(?![しす観者人成])

しかし InDesign CS4 で試してみると、この3つの正規表現の挙動は少しずつ変わり、探したいの達の用例だけでなく「上位下達」や「調達」の達にもマッチしてしまいます。

どうも肯定的先読みの内側で OR `|` を使うのがまずいようなのですが、私の目的をうまく表現する方法はないでしょうか。

妥協案:
(?<![下調伝到発])達(?![しす観者人成])

OR を使うのはあきらめて、文字クラスに「下」だけを追加すれば実用には足りてしまうのですが、モヤモヤが残るので質問させていただきました。
[8819]Ruby 2.1.5 での挙動を示すURL 投稿者:cu39 投稿日:2015/11/12 00:13:37
Ruby 2.1.5 での挙動例のURLを付記します。ウェブ上で正規表現をテストできる Rubular というサイトを利用しています。
www.rubular.com/r/JAF1gxc68c
[8822]Re: InDesign CS4の肯定的先読みとOR表現の組み合わせ 投稿者:あるふぁ 投稿日:2015/11/12 14:27:14
「上意下」と「上位下」の混在が気になりますが、そこに起因する問題じゃなさそうですね。
どうも「InDesignの正規表現では(?<!A|B|C)のA,B,Cはどれも同じ文字数の正規表現でなくてはならない」という仮説で説明できそうな感じがします。

たとえば字数を合わせるために
(?<!..[調伝到発]|上位下)達(?![しす観者人成])
とすると、上位下達とともに伝達、調達などもはじくことができました。
しかし5文字目の『発達』の達はヒットしてしまう。これは前にヒットした『私達』との間に3文字もないからと理解できるのですが、これでは使い物にはなりませんね。
[8825]Re: InDesign CS4の肯定的先読みとOR表現の組み合わせ 投稿者:cu39 投稿日:2015/11/12 23:00:23
初歩的な誤字があり、申し訳ないです(これが原因だったら私の恥だけで終わったのですが……)。
それと、私が「肯定的先読み」と書いたものをすべて「否定的後読み」に訂正します。いろいろ凹んでいます。

> 「InDesignの正規表現では(?<!A|B|C)のA,B,Cはどれも同じ文字数の正規表現でなくてはならない」という仮説

素晴らしい洞察、ありがとうございます。自分だけで検証していても気がつけたかどうかという発想で、相談してよかった。
後ほど検証例を示しますが、私もそれが正しいと思います。

その前にまず、解決策です。誤字を直した文例から始めます。

> 私達は発達して上意下達の社会で仲間達へ情報を伝達し、人生を達観した達人など様々な人達とともに物資調達を達成します。この目的を達した暁には達者で暮らしたいです。

(?<![調伝到発])(?<!上意下)達(?![しす観者人成])
このように否定的後読みを単純に2つ連ねると、目的の動作になりました。これで当初の目的は満たされました。

字数問題を確かめるため、文例に「明朗闊達」を加えます。

> 私達は発達して上意下達の社会で仲間達へ情報を伝達し、人生を達観した達人など様々な人達とともに物資調達を達成します。この目的を達した暁には達者で明朗闊達に暮らしたいです。

(?<![調伝到発])(?<!上意下|明朗闊)達(?![しす観者人成])
2つめの内側で OR 条件を使ってもOKで、「字数を同じにする必要がある」仮説を裏付ける挙動です。

ここに「司馬懿仲達」を加え、 OR でつなぎます。

> 私達は発達して上意下達の社会で仲間達へ情報を伝達し、人生を達観した達人など様々な人達とともに物資調達を達成します。この目的を達した暁には達者で明朗闊達に暮らしたいです。司馬懿仲達はよく走ります。

(?<![調伝到発])(?<!上意下|明朗闊|司馬懿仲)達(?![しす観者人成])
これだと「司馬懿仲達」(の達)にヒットしてしまい、やはり仮説通り。
というわけで、3つめの後読み節を追加してみます。

(?<![調伝到発])(?<!上意下|明朗闊)(<?!司馬懿仲)達(?![しす観者人成])
これで「司馬懿仲達」も除外できました。
ここまで、あるふぁさんの洞察から外れる挙動はありません。InDesign の正規表現にはこういう制限があるということなのでしょう。

ちなみに先読み (?!A|B|C) なら字数が違ってもいけるようです。

> 私達は発達して上意下達の社会で仲間達へ情報を伝達し、人生を達観した達人など様々な人達とともに物資調達を達成します。この目的を達した暁には達者で明朗闊達に暮らしたいです。司馬懿仲達はよく走り、達磨大師は座禅ばかりしています。

(?<![調伝到発])(?<!上意下|明朗闊)(?<!司馬懿仲)達(?![しす観者人成]|磨大師)

他の処理系でも、後読みと先読みで微妙な違いがあるようですね。
お察しの通り、InDesignの正規表現で後読みを使う場合は固定文字長に限られます。
せうぞーさんの記事をご参照ください。
http://d.hatena.ne.jp/seuzo/20110402/1301732490

これは鬼雲でも同様です。以下引用です。

   戻り読みの式は固定文字長でなければならない。
   しかし、最上位の選択子だけは異なった文字長が許される。
   例. (?<=a|bc) は許可. (?<=aaa(?:b|cd)) は不許可

https://github.com/k-takata/Onigmo/blob/master/doc/RE.ja

鬼雲でも文字長はすべて可変というわけではありませんので、ご注意ください。
[8827]Re: InDesign CS4の肯定的先読みとOR表現の組み合わせ 投稿者:cu39 投稿日:2015/11/13 16:58:55
ありがとうございます。
せうぞーさんの記事はまさに私が出会った問題で、もっと検索してみるべきでした。
InDesignと鬼雲(Ruby)のどちらも後読み内で量指定子(? * + {n,m} など)が使えないのも大事なポイントですね。

鬼雲の場合は「後読みの (?<= の直後に A|B|C が現れる場合に限り、文字長違いが許容される」わけですね。
(最初に「選択子」を「選択肢」と思い込んで混乱し、理解まで少し時間がかかりました)
(?<=a|bb|ccc))x #=> valid
(?<=a(?:bb|cc))x #=> valid
(?<=a(?:bb|ccc))x #=> invalid
いやあ、ややこしい。
この記事の書き込み元へのリンク (コメントや質問などはこちらへどうぞ)