- PR -

文字列の右端の数値部分とその他の部分を一発で分離する正規表現

投稿者投稿内容
まさ
ベテラン
会議室デビュー日: 2002/11/15
投稿数: 74
投稿日時: 2006-08-25 21:34
まさです。

Java とは直接的な関係はありませんが...

ある文字列の右端の数値部分とその他の部分を一発で分離する正規表現を考えています。

コード:

  "ABC" => "ABC"、""
  "ABC123" => "ABC"、"123"
  "A1B2C3" => "A1B2C"、"3"



そこで考えたのが、「"(.*[^0-9])([0-9]*)"」だったのですが、
これだと数値だけの文字列の場合に意図した結果になりません。

期待値: "12345" => ""、"12345"
結果 : "12345" => "12345"、""

まぁ、そういう正規表現になってしまっているのですが...

正規表現には java.util.regex を使用しています。
一発で分離するのは難しいでしょうか?

お知恵をお貸しください。よろしくお願いします。
想馬
大ベテラン
会議室デビュー日: 2003/05/29
投稿数: 245
お住まい・勤務地: 神奈川・東京
投稿日時: 2006-08-25 22:54
^(.*?)([0-9]*)$

で、どうでしょう。
まさ
ベテラン
会議室デビュー日: 2002/11/15
投稿数: 74
投稿日時: 2006-08-25 23:16
が〜ん。

夕方くらいから今までずっと悩んでました...
完璧でございます... m(_ _)m

ありがとうございました。


Pattern の Javadoc がところどころ理解できず悩むことがしばしばです。
ちょっとそれますが、「強欲な数量子」はどういう風にマッチするのでしょうか...

[ メッセージ編集済み 編集者: まさ 編集日時 2006-08-25 23:16 ]
想馬
大ベテラン
会議室デビュー日: 2003/05/29
投稿数: 245
お住まい・勤務地: 神奈川・東京
投稿日時: 2006-08-25 23:33
引用:

まささんの書き込み (2006-08-25 23:16) より:
ちょっとそれますが、「強欲な数量子」はどういう風にマッチするのでしょうか...

[ メッセージ編集済み 編集者: まさ 編集日時 2006-08-25 23:16 ]


間違っているかもしれないので自信がありませんが・・・
強欲はそれ単体では最長と区別は無く、それ以降のパターンマッチで影響があるものだと理解しています。

あとJavadocで正規表現を理解するのは止めた方がいいと思います。
正規表現を勉強するのであれば「正規表現」で検索してヒットしたサイトを読むだけで基本的な使い方は全然大丈夫です。もっと詳しく勉強するのであればオライリーが出版している鈍器のような分厚い本を参照するといいと思います(結構高いです)。

ちなみに今回まささんが実現しようとしたパターンのキモは最短一致と、$と最長の組み合わせだと思っています。
paniponi-x
常連さん
会議室デビュー日: 2006/01/14
投稿数: 27
投稿日時: 2006-08-26 01:16
強欲な量指定子ですが、これは他の量指定子と比較すると決してバックトラックしないという
特徴を持ちます。つまり、

コード:
^.+9$

^.++9$



という正規表現に対して abc123456789 という文字列のマッチングを試みた場合
前者はマッチしますが、後者はマッチしません。なぜなら、前者は
.+ がいったん文字列の末尾まで行き着いてマッチに失敗したあと、一文字
戻して(バックトラック)後続の部分文字列のマッチングを試みます
(そしてこの場合は成功する)。

一方で後者の場合はいったんつかんだ文字列を手放すことは決してないので
9にマッチさせる部分文字列を得ることができず全体が失敗します。

この例だけ見ると何のためにあるのやら分からないと思いますが、バックトラックを
必要ないところで抑制できることで、全体のマッチングの効率を大幅に向上させる
ことが可能になります。

しかし、詳説正規表現ぐらいで鈍器扱いされてしまうのなら、CJKV本なんかは
どうなってしまうのでしょうか…
まさ
ベテラン
会議室デビュー日: 2002/11/15
投稿数: 74
投稿日時: 2006-08-28 13:57
想馬 さん>
引用:

想馬さんの書き込み (2006-08-25 23:33) より:

ちなみに今回まささんが実現しようとしたパターンのキモは最短一致と、$と最長の組み合わせだと思っています。



はい。ここは理解できました。

引用:

あと Javadoc で正規表現を理解するのは止めた方がいいと思います。
正規表現を勉強するのであれば「正規表現」で検索してヒットしたサイトを読むだけで基本的な使い方は全然大丈夫です。



そうですか。
当方、正規表現を触るのが Java が初めてというわけではなく、
Perl その他(grep など) で触ったことはあります。

ただし、理解度としては
・"." が任意の文字にマッチング
・"*" をつけると0文字以上の繰り返し
・"+" をつけると1文字以上の繰り返し
・"[0-9]" は数値にマッチ
くらいの理解度しか持っておらず、中途半端に知っているおかげで
「正規表現についてきちんと検索したのか?」というと、できていなかったと思います。
「最長・最短一致」では無く「前方一致・不一致、後方一致・不一致」ばかり探していました。
すいませんでした(また、言い訳をつらつら書いてすいません)。


paniponi-x さん>
引用:

paniponi-xさんの書き込み (2006-08-26 01:16) より:

一方で後者の場合はいったんつかんだ文字列を手放すことは決してないので
9にマッチさせる部分文字列を得ることができず全体が失敗します。



それは、"abc123456789" の文字列が "^.++" にマッチしてしまうからだと思いますがあっていますか?
そうすると、「強欲な量指定子」を使用する場合には "^.++" と記述するのがそもそも間違い(?)と思ったのですが、この認識もあっていますか?


引用:

この例だけ見ると何のためにあるのやら分からないと思いますが、バックトラックを
必要ないところで抑制できることで、全体のマッチングの効率を大幅に向上させる
ことが可能になります。



確かによくわかりません。
お時間がありましたら、もう少し例をいただけませんか。
明智重蔵
大ベテラン
会議室デビュー日: 2005/09/05
投稿数: 127
投稿日時: 2006-08-28 14:20
^(((?![0-9]*$).)*)(.*)$

一応、これでもできますけど
最小マッチを使ったほうが分かりやすいですね


正規表現パズル
http://oraclesqlpuzzle.hp.infoseek.co.jp/regex/index.html
paniponi-x
常連さん
会議室デビュー日: 2006/01/14
投稿数: 27
投稿日時: 2006-08-29 01:28
引用:

それは、"abc123456789" の文字列が "^.++" にマッチしてしまうからだと思いますがあっていますか?



はい。その通りです。

引用:

そうすると、「強欲な量指定子」を使用する場合には "^.++" と記述するのがそもそも間違い(?)と思ったのですが、この認識もあっていますか?



はい。この例ではそう書いてはいけません。

カッコのネスティングチェックなどで使われる例があるのですが、Perlのもので
Javaの正規表現では書けない(定義が再帰的なものになっている)ので、
何か良い例がないか考えてみます。

ところで引用するときに **さんの書き込みより といった表記はどうやって有効にできるのでしょうか?
FAQ見たけど見当たらないし。

[ メッセージ編集済み 編集者: paniponi-x 編集日時 2006-08-29 01:30 ]

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