- PR -

2つの正規表現の組み合わせ

投稿者投稿内容
translator
会議室デビュー日: 2008/01/16
投稿数: 7
投稿日時: 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
にマッチするわけではありません。
このような問題を解決する一般的な方法があれば教えていただけないでしょうか。
囚人
ぬし
会議室デビュー日: 2005/08/13
投稿数: 1019
投稿日時: 2008-01-16 14:58
>文字列を検索しようとした場合、
以降が何を仰ってるのかさっぱりわかりませんが、
今回の例では

^[02-9][0-9]*\.[0-9]*[013-9]$

と同じ事がしたいって事ですか?(\d じゃなくて[0-9]使いましたが同じです)


#バックスラッシュを修正
_________________
囚人のジレンマな日々



[ メッセージ編集済み 編集者: 囚人 編集日時 2008-01-16 15:02 ]
translator
会議室デビュー日: 2008/01/16
投稿数: 7
投稿日時: 2008-01-16 15:07
返答ありがとうございます。
今回の例では確かにそういうことなのですが、
このようにして構成しなければならない正規表現がたくさんあり、
一般的に解決できる方法を知りたいと思っております。
\Gを使えば出来ないかとも思ったのですが、
A(?<!\GB)
のようにしても\Gが前回マッチの最終位置になるので、うまくいきませんでした。
今回のマッチの最初の位置を表すメタ文字があればうまくいくと思うのですが。
よねKEN
ぬし
会議室デビュー日: 2003/08/23
投稿数: 472
投稿日時: 2008-01-16 15:58
引用:

translatorさんの書き込み (2008-01-16 13:54) より:
Aという正規表現とBという正規表現があった時、
Aにマッチさせて、マッチした後に、そのマッチ全体がBにはマッチしない文字列を検索するにはどうすればよいのでしょうか。
:中略
このような問題を解決する一般的な方法があれば教えていただけないでしょうか。



ある条件での検索結果からそのうちの例外的なパターンだけを除外したいということですよね。
私はtranslatorさんが書かれている通りの手順がそのままでよいと思います。

一つの正規表現で解決しなくても、2つの正規表現に対して
「Aにマッチし、かつ、Aにマッチした部分文字列はBにマッチしない」
という判断で期待する検索結果かどうかを判断すればよいと思います。
translator
会議室デビュー日: 2008/01/16
投稿数: 7
投稿日時: 2008-01-16 16:20
よねKENさん
返答ありがとうございます。
つまり、一つの正規表現上ではなく、プログラム上で実現する方法が良いということでしょうか。
たしかにそれがわかりやすいかもしれません。
ただ、現在あるソースでは、正規表現で多くのことを行っています。
できればプログラム改修を行わずに実現したいと思っております。
また、正規表現の理解を増すためにも、正規表現上のみで解決策があれば知りたいと思うのですが、いかがでしょうか。
明智重蔵
大ベテラン
会議室デビュー日: 2005/09/05
投稿数: 127
投稿日時: 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 ]
translator
会議室デビュー日: 2008/01/16
投稿数: 7
投稿日時: 2008-01-16 16:34
明智重蔵さん
興味深い回答ありがとうございます。
たしかにこの方法は固定長でしたらうまくいきます。
しかし、非固定長の場合ではうまくいかないような気がするのですが。
たとえば、
最初の例で挙げた正規表現ですと、
(?=(\d+\.\d+))(?!1\d*\.\d*2)\1
としますと、
1.23
にはマッチしません。
結局(?!1\d*\.\d*2)の部分で\1の最終位置まで一致するかを見ることができないことが問題です。
translator
会議室デビュー日: 2008/01/16
投稿数: 7
投稿日時: 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 ]

スキルアップ/キャリアアップ(JOB@IT)