質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Q&A

解決済

2回答

2480閲覧

C#正規表現を用いたパターンマッチの評価順について

退会済みユーザー

退会済みユーザー

総合スコア0

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

0グッド

0クリップ

投稿2018/06/18 08:00

前提・実現したいこと

WPFのアプリケーション開発で入力された文字列がある指定の形式に合っているか
正規表現を用いて確認したい。

発生している問題・エラーメッセージ

2パターンの形式のうちどちらかに合っていればOK、それ以外であればNGと判定して
その後の処理をしたいのですが、正規表現の評価順が分からなかったため、どの様な順番で
評価されているのか教えていただきたいです。

該当のソースコード

C#

1// 検索対象文字列(テキストボックスなど外部から入力) 2var target = "KA123456"; 3// 正規表現パターン 4var regexA = new Regex(@"(A\d{6}|KA\d{6})"); 5// パターンマッチ 6var matchA = regexA.Match(target); 7if (matchA.Success == true) 8{ 9 // パターンに合っている時の処理 10}

試したこと

上記コードの様に検索したい文字列が正規表現のどちらにも該当する場合には、
どちらをMatchで拾うのでしょうか。ネットで調べてみたところ、左側から評価されると
書いていたのをみたので試しに|(OR)の記号の前後を入れ替えても結果は
変わらず、A\d{6}にマッチしていました。
どちらのパターンにマッチしているかでその後の処理を変えたい場合には
下記の様に一回ずつマッチをして確認するしかないのでしょうか。

説明が下手で分かりにくいかもしれませんがご回答よろしくお願いします。

C#

1// 検索対象文字列(テキストボックスなど外部から入力) 2var target = "KA123456"; 3// 正規表現パターン 4var regexA = new Regex(@"A\d{6}"); 5var regexB = new Regex(@"KA\d{6}"); 6// パターンマッチ 7var matchA = regexA.Match(target); 8var matchB = regexB.Match(target); 9// KAから始まる数字6桁の場合にはどちらのパターンにもマッチするため、ifの入れ子で判定 10if (matchA.Success == true) 11{ 12 if (matchB.Success == true) 13 { 14 // パターンBに合っている時の処理 15 } 16 else 17 { 18 // パターンAに合っている時の処理 19 } 20}

補足情報(FW/ツールのバージョンなど)

Visual Studio 2017
.NET Framework 4.6.1

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

takabosoft

2018/06/18 08:25

手元の環境だと KA\d{6} の方にマッチするようなのですがどうやって確認されましたか?
退会済みユーザー

退会済みユーザー

2018/06/18 08:30 編集

ご回答ありがとうございます。 すみません。おっしゃる通りKAの間違いです。
guest

回答2

0

ベストアンサー

マッチ結果が長い方かtargetの頭から走査した時に最初にマッチする方かどちらかかなと思いましたが、

Regex(@"(A\d{6}|KA\d{5})");

Regex(@"(KA\d{5}|A\d{6})");

で試したところ(マッチ結果の文字数を揃えています)、どちらもKAの方がヒットしたので、targetの頭から走査した時に最初にマッチする方なんでしょうね。

ただ、仮にこれの順番が判ったところで、その後の分岐は別途書かないといけないと思うのですがどうなんでしょうか。

自分なら以下のように書きます。

csharp

1 var target = "KA123456"; 2 var matchKA = Regex.Match(target, @"KA\d{6}"); 3 if (matchKA.Success) 4 { 5 Debug.WriteLine($"KAにマッチ:{matchKA.Value}"); 6 } 7 else 8 { 9 var matchA = Regex.Match(target, @"A\d{6}"); 10 if (matchA.Success) 11 { 12 Debug.WriteLine($"Aにマッチ:{matchA.Value}"); 13 } 14 }

投稿2018/06/18 09:01

編集2018/06/18 09:03
takabosoft

総合スコア8356

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2018/07/05 05:15

ご回答ありがとうございます。takabosoftさんの言う通り結局分岐で判断することにしました。 返信が遅くなってしまいましたが、無事に解決することができました。 ありがとうございます。
guest

0

if (matchA.Success || matchB.Success) { if (matchA.Success) { } else { } }

&& とか || は、先から判断する。
そのため、nullチェックを先に書かないとだめとかそういうのがある。

やりたい事的には、
matchA matchB を両方Trueになるのがあるとだめな書き方だけど、
こんなのでいいんじゃない?

投稿2018/06/18 08:11

kiichi54321

総合スコア1984

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2018/06/18 08:36

ご回答ありがとうございます。 正規表現を論理和で一つにまとめた方法でできれば後で見たときに分かりやすい、変数の数を減らせると思ったのですが2パターンに分けて処理するしかないでしょうか。 ちなみにどちらのパターンにも当てはまることがあります。 二つの商品があり、片方はAで始まる数字6桁のロット番号、もう片方はKAから始まる数字6桁のロット番号で管理しており、それぞれの商品でその後の処理を切り替えするために今回の質問をさせていただきました。
kiichi54321

2018/06/18 09:00

よく見たら、matchAと matchBは、包含関係じゃん。だったら、順番を工夫するだけで十分でしょう。 あと、これくらいなら、全て正規表現でやらず、 target.First() == 'K' とかで判別すればいいじゃないとか思いますね。
退会済みユーザー

退会済みユーザー

2018/07/05 05:18

単純にどっちの商品のロットなのか判別するだけならおっしゃる通り始まりの文字だけ見れば良いのですが、桁数が足りないとエラーにしたいなどロット番号の形式チェックもしたかったので正規表現を使いました。 ご回答ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問