C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[8]: 正規表現の質問です


(過去ログ 132 を表示中)

[トピック内 14 記事 (1 - 14 表示)]  << 0 >>

■78226 / inTopicNo.1)  正規表現の質問です
  
□投稿者/ サミット (1回)-(2015/12/25(Fri) 12:55:05)

分類:[VB.NET/VB2005 以降] 

使用言語:VB2008ですが、正規表現の質問です。

文字列から英数字とハイフンのみで構成されている部分を抽出したいのですが、
もしかっこ( )で囲まれている場合には、かっこも含めて抽出したいのです。

例えば、変な例で申し訳ないのですが、

****
商品名:AB-100(ブラック)
シリアル番号:123-456-7890(PV限定版)
掲載ページ:100(A-2)
****

というテキストより

AB-100
123-456-7890
PV
100
(A-2)

という文字を抽出したいのです。

そこで、最近勉強を始めた正規表現を使ってみようと思い、
以下のようなパイプ「|」を使ったパターンを考えてみました。

\([\dA-Za-z\-]+\)|[\dA-Za-z\-]+

でも、パイプの前後で同じ「[\dA-Za-z\-]+」というパターンが繰り返されるし、
上のパターンがもっと複雑になったら大変だと思い、
もっとシンプルな表現がないかを知りたくて投稿しました。


正規表現の上級テクニックをご教示頂けるとありがたいです。
引用返信 編集キー/
■78227 / inTopicNo.2)  Re[1]: 正規表現の質問です
□投稿者/ WebSurfer (752回)-(2015/12/25(Fri) 13:14:36)
No78226 (サミット さん) に返信

> もしかっこ( )で囲まれている場合には、かっこも含めて抽出したいのです。

( と ) はメタ文字で、パターンの中では特別な意味を持つのでエス
ケープ([ と ] で囲う)しないとうまくいかないと思います。

以下の記事は「ASP.NET の」となっていますが ASP.NET に限らず
.NET 全般に役立つと思います。

ASP.NET の正規表現
https://msdn.microsoft.com/ja-jp/library/ms972966.aspx
引用返信 編集キー/
■78228 / inTopicNo.3)  Re[1]: 正規表現の質問です
□投稿者/ WebSurfer (753回)-(2015/12/25(Fri) 13:22:42)
No78226 (サミット さん) に返信

すみません、\ でエスケープされてましたね。

質問はパターン \([\dA-Za-z\-]+\)|[\dA-Za-z\-]+ で望みどおりの結果になるが、
もっと簡単に書けないかということでしょうか?
引用返信 編集キー/
■78229 / inTopicNo.4)  Re[1]: 正規表現の質問です
□投稿者/ 魔界の仮面弁士 (618回)-(2015/12/25(Fri) 15:44:09)
No78226 (サミット さん) に返信
> 以下のようなパイプ「|」を使ったパターンを考えてみました。
> \([\dA-Za-z\-]+\)|[\dA-Za-z\-]+

これだと、全角の「0」までマッチしますが構わないのでしょうか?
少なくとも、全角アルファベットは除外されていますよね。

全角数字を含めない場合は、\d ではなく [0-9] を使ってみてください。
引用返信 編集キー/
■78230 / inTopicNo.5)  Re[2]: 正規表現の質問です
□投稿者/ サミット (2回)-(2015/12/25(Fri) 21:36:10)
> 質問はパターン \([\dA-Za-z\-]+\)|[\dA-Za-z\-]+ で望みどおりの結果になるが、
> もっと簡単に書けないかということでしょうか?

はい。仰るとおりです。
今後、[\dA-Za-z\-]+のパターンをもっと複雑なものにしようと思い、
それを2つ重ねるのもどうかと思いまして。

とは言え、単に[\dA-Za-z\-]+の部分をリテラルや変数にして、
文字列結合すればパターン文字列の作成は何とかスッキリできそうですが。


> これだと、全角の「0」までマッチしますが構わないのでしょうか?
> 少なくとも、全角アルファベットは除外されていますよね。
>
> 全角数字を含めない場合は、\d ではなく [0-9] を使ってみてください。

アドバイスありがとうございます。
とりあえず、[\dA-Za-z\-]+のパターンはあくまでも例として
捉えて頂ければ幸いです。
引用返信 編集キー/
■78231 / inTopicNo.6)  Re[3]: 正規表現の質問です
□投稿者/ shu (793回)-(2015/12/25(Fri) 22:02:59)
No78230 (サミット さん) に返信

すべてを正規表現で行わなければパターンを短くすることができます。
例)

        Dim reg As New Regex("\(?(?<v>[0-9a-d\-]+)\)?", RegexOptions.IgnoreCase)

        Dim m = reg.Match(TextBox1.Text)
        ListBox1.Items.Clear()
        Do While m.Success
            Dim value = m.Value

            If Not value.StartsWith("(") OrElse Not value.EndsWith(")") Then
                value = m.Groups("v").Value
            End If

            ListBox1.Items.Add(value)

            m = m.NextMatch
        Loop

引用返信 編集キー/
■78232 / inTopicNo.7)  Re[3]: 正規表現の質問です
□投稿者/ WebSurfer (754回)-(2015/12/26(Sat) 19:50:00)
No78230 (サミット さん) に返信

> とは言え、単に[\dA-Za-z\-]+の部分をリテラルや変数にして、
> 文字列結合すればパターン文字列の作成は何とかスッキリできそうですが。

具体的にどういうことを考えているのか質問者さんの意図を理解できていませんが、そ
れで「スッキリ」とは行かなくて、分かりにくくするだけのような気がしますが。

個人的には今のままで十分分かりやすいので、これをいろいろひねって分かりにくい方
向に持って行く必要はないと思います。

むしろ、タダでさえわかりにくい正規表現を後から保守する人が分かりやすくするため
に、コメントをつけてもいいぐらいだと思います。例えば以下のように:

Regex rgx = new Regex(@"
    \([\dA-Za-z\-]+\)   #カッコで囲われた英数字ハイフンが一文字以上
    |                   #または
    [\dA-Za-z\-]+       #英数字ハイフンが一文字以上・・・とマッチ",
    RegexOptions.IgnorePatternWhitespace);

引用返信 編集キー/
■78233 / inTopicNo.8)  Re[4]: 正規表現の質問です
□投稿者/ なちゃ (89回)-(2015/12/27(Sun) 02:33:03)
No78232 (WebSurfer さん) に返信
> 具体的にどういうことを考えているのか質問者さんの意図を理解できていませんが、そ
> れで「スッキリ」とは行かなくて、分かりにくくするだけのような気がしますが。
>
> 個人的には今のままで十分分かりやすいので、これをいろいろひねって分かりにくい方
> 向に持って行く必要はないと思います。

ただ単に、同じ表現部分が例えばもっと何十文字となった場合などに、それを繰り返して書いているとメンテナンスしにくかったり、読んだときに同一なのかそうでないのか分かりにくかったり、とかそういう話でしょう。
で、同じ部分を変数に入れといて、連結すれば同じだということが明確&繰り返しでミスったりすることがないとか、そういう意味でしょう。

※プログラミング的にはまあ普通のよくある発想

正規表現の機能での話ですが、名前付きのグループにして前方参照ってできる系統の正規表現エンジンもあったような気もしますが、.NETではできなかったかな…

引用返信 編集キー/
■78234 / inTopicNo.9)  Re[5]: 正規表現の質問です
□投稿者/ なちゃ (90回)-(2015/12/27(Sun) 02:39:01)
No78233 (なちゃ さん) に返信
> 正規表現の機能での話ですが、名前付きのグループにして前方参照ってできる系統の正規表現エンジンもあったような気もしますが、.NETではできなかったかな…

番号または名前付きのキャプチャグループで前方参照出来るっぽいですね。
https://msdn.microsoft.com/ja-jp/library/thwdfzxy%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396

\(([\dA-Za-z\-]+)\)|\1
とかかな?
※試してないので間違ってるかもしれませんが

分かりにくい場合は名前付きキャプチャグループにすればいいかな。

引用返信 編集キー/
■78235 / inTopicNo.10)  Re[6]: 正規表現の質問です
□投稿者/ なちゃ (91回)-(2015/12/27(Sun) 02:41:39)
No78234 (なちゃ さん) に返信
> \(([\dA-Za-z\-]+)\)|\1
> とかかな?
> ※試してないので間違ってるかもしれませんが

どっちかというと、
([\dA-Za-z\-]+)|\(\1\)
のが分かりやすいか…微妙…

引用返信 編集キー/
■78236 / inTopicNo.11)  Re[7]: 正規表現の質問です
□投稿者/ なちゃ (92回)-(2015/12/27(Sun) 02:43:33)
No78235 (なちゃ さん) に返信
> どっちかというと、
> ([\dA-Za-z\-]+)|\(\1\)
> のが分かりやすいか…微妙…

何度もすみません、これだと優先度(マッチ順)の問題でダメかも、ダメだったら忘れてください。
引用返信 編集キー/
■78241 / inTopicNo.12)  Re[6]: 正規表現の質問です
□投稿者/ くりーね (1回)-(2015/12/28(Mon) 03:54:03)
No78234 (なちゃ さん) に返信
> \(([\dA-Za-z\-]+)\)|\1
> とかかな?
> ※試してないので間違ってるかもしれませんが

んー、間違いかと。

代替構成体「|」の左側が一致しないとキャプチャされないので、
右側の一致が試されるとき、「\1」は常に未定義です...。

件の処理は、代替構成体の条件一致を使って、

(\()?[-0-9A-Za-z]+(?(1)\))

こんな感じで。

このままだと、「(」のみで「)」のない入力、たとえば「(PV限定版)」のとき、
分かりやすく無駄にバックトラックしてくれるので、少し改良して、

(?>(\()?[-0-9A-Za-z]+)(?(1)\))

こんな感じ。

それでも、まだ、shu さんの No78231 のコードのほうが効率的に動作するはず。
サミットさんのパターンや僕のパターンは、「(」のみで「)」のない入力のとき、
「[-0-9A-Za-z]+」が 2 回処理されてしまうのが敗因です。

引用返信 編集キー/
■78242 / inTopicNo.13)  Re[7]: 正規表現の質問です
□投稿者/ なちゃ (93回)-(2015/12/28(Mon) 10:17:26)
No78241 (くりーね さん) に返信
> ■No78234 (なちゃ さん) に返信
>>\(([\dA-Za-z\-]+)\)|\1
>>とかかな?
>>※試してないので間違ってるかもしれませんが
>
> んー、間違いかと。
>
> 代替構成体「|」の左側が一致しないとキャプチャされないので、
> 右側の一致が試されるとき、「\1」は常に未定義です...。

おおお、すみません、大間違いでしたね。
申し訳ない。
引用返信 編集キー/
■78244 / inTopicNo.14)  Re[8]: 正規表現の質問です
□投稿者/ サミット (3回)-(2015/12/28(Mon) 14:46:35)
皆様、貴重なアドバイスありがとうございました。
色々と考えましたが、何も正規表現だけに頼る必要はない
(場合によってはややこしくなる)ということを理解しました。

その意味では、くりーね さんの仰る通り、
今回のケースではshu さんの方法が一番よさそうです。

今回の質問は解決とさせて頂きます。
今後ともよろしくお願い申し上げます。
解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -