- - PR -
2つの正規表現の組み合わせ
投稿者 | 投稿内容 | ||||
---|---|---|---|---|---|
|
投稿日時: 2008-01-16 13:54
Aという正規表現とBという正規表現があった時、
Aにマッチさせて、マッチした後に、そのマッチ全体がBにはマッチしない文字列を検索するにはどうすればよいのでしょうか。 たとえば、 \d+\.\d+ にマッチするが、そのマッチ文字列全体が 1\d*\.\d*2 にマッチしないような 文字列を検索しようとした場合、 (?!1\d*\.\d*2)\d+\.\d+ とすると 1.23 にはマッチしなくなります。 また、 \d+\.\d+(?<!1\d*\.\d*2) とすると 21.2 にはマッチしなくなります。 しかし、どちらの場合にも、数字全体が 1\d*\.\d*2 にマッチするわけではありません。 このような問題を解決する一般的な方法があれば教えていただけないでしょうか。 | ||||
|
投稿日時: 2008-01-16 14:58
>文字列を検索しようとした場合、
以降が何を仰ってるのかさっぱりわかりませんが、 今回の例では ^[02-9][0-9]*\.[0-9]*[013-9]$ と同じ事がしたいって事ですか?(\d じゃなくて[0-9]使いましたが同じです) #バックスラッシュを修正 _________________ 囚人のジレンマな日々 [ メッセージ編集済み 編集者: 囚人 編集日時 2008-01-16 15:02 ] | ||||
|
投稿日時: 2008-01-16 15:07
返答ありがとうございます。
今回の例では確かにそういうことなのですが、 このようにして構成しなければならない正規表現がたくさんあり、 一般的に解決できる方法を知りたいと思っております。 \Gを使えば出来ないかとも思ったのですが、 A(?<!\GB) のようにしても\Gが前回マッチの最終位置になるので、うまくいきませんでした。 今回のマッチの最初の位置を表すメタ文字があればうまくいくと思うのですが。 | ||||
|
投稿日時: 2008-01-16 15:58
ある条件での検索結果からそのうちの例外的なパターンだけを除外したいということですよね。 私はtranslatorさんが書かれている通りの手順がそのままでよいと思います。 一つの正規表現で解決しなくても、2つの正規表現に対して 「Aにマッチし、かつ、Aにマッチした部分文字列はBにマッチしない」 という判断で期待する検索結果かどうかを判断すればよいと思います。 | ||||
|
投稿日時: 2008-01-16 16:20
よねKENさん
返答ありがとうございます。 つまり、一つの正規表現上ではなく、プログラム上で実現する方法が良いということでしょうか。 たしかにそれがわかりやすいかもしれません。 ただ、現在あるソースでは、正規表現で多くのことを行っています。 できればプログラム改修を行わずに実現したいと思っております。 また、正規表現の理解を増すためにも、正規表現上のみで解決策があれば知りたいと思うのですが、いかがでしょうか。 | ||||
|
投稿日時: 2008-01-16 16:21
(?=([0-9]{3}))(?![5-9]{3})\1
検索対象 123456789 参考リンク Javaの文字クラスの集合演算 http://oraclesqlpuzzle.hp.infoseek.co.jp/regex/regex-3-29.html _________________ [ メッセージ編集済み 編集者: 明智重蔵 編集日時 2008-01-16 16:21 ] | ||||
|
投稿日時: 2008-01-16 16:34
明智重蔵さん
興味深い回答ありがとうございます。 たしかにこの方法は固定長でしたらうまくいきます。 しかし、非固定長の場合ではうまくいかないような気がするのですが。 たとえば、 最初の例で挙げた正規表現ですと、 (?=(\d+\.\d+))(?!1\d*\.\d*2)\1 としますと、 1.23 にはマッチしません。 結局(?!1\d*\.\d*2)の部分で\1の最終位置まで一致するかを見ることができないことが問題です。 | ||||
|
投稿日時: 2008-01-16 16:51
明智重蔵さんの例からすこし考えてみました。
上の例ですと、 (?=(\d+\.\d+))(?((1\d*\.\d*2))\1(?<!\2)|\1) でうまくいきます。 つまり、 (?=(A))(?((B))\1(?<!\2)|\1) という構文になりました。かなり複雑なのが気持ち悪いですが。 もう少し発展させて、 Aにマッチする。しかし、その全体がBにもCにもマッチしないというように条件を増やすと、 (?=(A))(?((B))\1(?<!\2)|(?((C))\1(?<!\3)|\1)) となっていきます。 ただ、これでもうまくいかない例があることを発見してしまいました。 [ メッセージ編集済み 編集者: translator 編集日時 2008-01-16 17:02 ] [ メッセージ編集済み 編集者: translator 編集日時 2008-01-16 17:14 ] |