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

わんくま同盟

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

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

ツリー一括表示

正規表現の考え方がわかりません /夜叉丸 (17/09/05(Tue) 09:40) #85005
Re[1]: 正規表現の考え方がわかりません /ペイビン (17/09/05(Tue) 10:05) #85007
│├ Re[2]: 正規表現の考え方がわかりません /WebSurfer (17/09/05(Tue) 10:54) #85009
│└ Re[2]: 正規表現の考え方がわかりません /夜叉丸 (17/09/05(Tue) 12:46) #85013
Re[1]: 正規表現の考え方がわかりません /WebSurfer (17/09/05(Tue) 10:47) #85008
│└ Re[2]: 正規表現の考え方がわかりません /夜叉丸 (17/09/05(Tue) 12:49) #85014
│  ├ Re[3]: 正規表現の考え方がわかりません /WebSurfer (17/09/05(Tue) 15:07) #85021
│  ├ Re[3]: 正規表現の考え方がわかりません /WebSurfer (17/09/05(Tue) 15:53) #85024
│  │└ Re[4]: 正規表現の考え方がわかりません /Hongliang (17/09/05(Tue) 16:03) #85025
│  │  └ Re[5]: 正規表現の考え方がわかりません /WebSurfer (17/09/05(Tue) 17:16) #85026
│  │    └ Re[6]: 正規表現の考え方がわかりません /魔界の仮面弁士 (17/09/05(Tue) 18:47) #85028
│  │      └ Re[7]: 正規表現の考え方がわかりません /夜叉丸 (17/09/12(Tue) 11:49) #85128
│  │        └ Re[8]: 正規表現の考え方がわかりません /魔界の仮面弁士 (17/09/12(Tue) 12:11) #85131
│  └ Re[3]: 正規表現の考え方がわかりません /WebSurfer (17/09/05(Tue) 19:27) #85030
│    └ Re[4]: 正規表現の考え方がわかりません /夜叉丸 (17/09/12(Tue) 10:20) #85122
│      ├ Re[5]: 正規表現の考え方がわかりません /Hongliang (17/09/12(Tue) 10:38) #85123
│      │└ Re[6]: 正規表現の考え方がわかりません /夜叉丸 (17/09/12(Tue) 10:48) #85124
│      └ Re[5]: 正規表現の考え方がわかりません /WebSurfer (17/09/12(Tue) 12:11) #85130
Re[1]: 正規表現の考え方がわかりません /魔界の仮面弁士 (17/09/05(Tue) 10:57) #85010
  └ Re[2]: 正規表現の考え方がわかりません /夜叉丸 (17/09/05(Tue) 13:55) #85015
    └ Re[3]: 正規表現の考え方がわかりません /Hongliang (17/09/05(Tue) 14:13) #85016
      └ Re[4]: 正規表現の考え方がわかりません /夜叉丸 (17/09/05(Tue) 14:28) #85017
        └ Re[5]: 正規表現の考え方がわかりません /ペイビン (17/09/05(Tue) 14:37) #85019
          └ Re[6]: 正規表現の考え方がわかりません /夜叉丸 (17/09/05(Tue) 14:49) #85020
            ├ Re[7]: 正規表現の考え方がわかりません /shu (17/09/05(Tue) 15:10) #85022
            └ Re[7]: 正規表現の考え方がわかりません /Hongliang (17/09/05(Tue) 15:43) #85023
              └ Re[8]: 正規表現の考え方がわかりません /ペイビン (17/09/05(Tue) 18:20) #85027
                └ Re[9]: 正規表現の考え方がわかりません /夜叉丸 (17/09/12(Tue) 09:43) #85121


親記事 / ▼[ 85007 ] ▼[ 85008 ] ▼[ 85010 ]
■85005 / 親階層)  正規表現の考え方がわかりません
□投稿者/ 夜叉丸 (69回)-(2017/09/05(Tue) 09:40:09)

分類:[.NET 全般] 

正規表現の考え方を教えてください

ra.ToString() = "{X=3, Y=6, Width=9, Height=12}"
Match m = new Regex(@"{X=(?<X>[-]*\d+),Y=(?<Y>[-]*\d+),Width=(?<Width>[-]*\d+),Height=(?<Height>[-]*\d+)}").Match(ra.ToString());
int ix = (int.TryParse(m.Groups["X"].ToString(), out ix)) ? ix : 0;

この場合
"3" = "(?<X>[-]*\d+)" であらわされるということですよね。

?<X> でグループを表す
[-] 連続した文字範囲の1文字     : あるかもしれないしないかもしれないマイナスフラグ
* 直前の文字が0回以上繰り返す。  : なので先頭だから繰り返さないので0回以上?
\d 0から9までの数字       : 数字を使用
+ 直前の文字が1回以上繰り返す。 : 数字が連続する

で認識しました。
ところが同様にfloat の場合どうすればよいのかわかりません。

raf.ToString() = "{X=3.1, Y=6.2, Width=9.3, Height=12.4}"

"?<X>[-]*\d+" ここまではそのまま使えばよいと思いますが

.はあるかもしれないしないかもしれないので [.] を使いました。"?<X>[-]*\d+[.]"
次に来るのは数字ですが、前に '.' があるかもしれないので 直前の文字が0回以上繰り返すを使用して
"?<X>[-]*\d+[.]*\d"
としたのですがだめでした。

また、.も文字だからとして
(?<X>[-]*\w+)
これもだめでした。

正規表現の考え方が全く分からないのですが
どうすれば理解できるのでしょうか?

[ □ Tree ] 返信 編集キー/

▲[ 85005 ] / ▼[ 85009 ] ▼[ 85013 ]
■85007 / 1階層)  Re[1]: 正規表現の考え方がわかりません
□投稿者/ ペイビン (1回)-(2017/09/05(Tue) 10:05:09)
[ ]の中のハイフン「-」って、[A-Z](AからZまでの文字にマッチ)のようにつかうものだと思っていましたが、
[-]と書いてしまうと、ただの「-」にマッチするだけなのではないでしょうか?
(違っていたらゴメンナサイ)
[ 親 85005 / □ Tree ] 返信 編集キー/

▲[ 85007 ] / 返信無し
■85009 / 2階層)  Re[2]: 正規表現の考え方がわかりません
□投稿者/ WebSurfer (1292回)-(2017/09/05(Tue) 10:54:11)
No85007 (ペイビン さん) に返信
> [ ]の中のハイフン「-」って、[A-Z](AからZまでの文字にマッチ)のようにつかうものだと思っていましたが、
> [-]と書いてしまうと、ただの「-」にマッチするだけなのではないでしょうか?


上記の点については、以下の記事の「文字クラス」のセクションが参考になると思います。

ASP.NET の正規表現
https://msdn.microsoft.com/ja-jp/library/ms972966.aspx

"ハイフン文字は、先頭の文字でない場合に限り、文字クラス内で特別な意味を持ちます"

"範囲内にハイフンを含める必要がある場合は、それを先頭の文字として指定してください"

[ 親 85005 / □ Tree ] 返信 編集キー/

▲[ 85007 ] / 返信無し
■85013 / 2階層)  Re[2]: 正規表現の考え方がわかりません
□投稿者/ 夜叉丸 (70回)-(2017/09/05(Tue) 12:46:56)
No85007 (ペイビン さん) に返信
> [ ]の中のハイフン「-」って、[A-Z](AからZまでの文字にマッチ)のようにつかうものだと思っていましたが、
> [-]と書いてしまうと、ただの「-」にマッチするだけなのではないでしょうか?
> (違っていたらゴメンナサイ)

私もそう思います。
なので、マイナスがあれば マイナスをとってくるし、
なければ何も取ってこないのだという認識だったのですが。
[ 親 85005 / □ Tree ] 返信 編集キー/

▲[ 85005 ] / ▼[ 85014 ]
■85008 / 1階層)  Re[1]: 正規表現の考え方がわかりません
□投稿者/ WebSurfer (1291回)-(2017/09/05(Tue) 10:47:26)
No85005 (夜叉丸 さん) に返信

文字列の条件を明確にしていただかないとなかなかレスしずらいです。

最初の例のパターン [-]*\d+ は、最初に '-' が 0 回以上の繰り返し、その次が数字
の 1 回以上の繰り返しになりますが、そうすると例えば以下の入力にもマッチするは
ずです。

-----3
00000000
2147483648 (Int32.MaxValue を超える数字)

そういう入力はダメなら、それにはマッチしないパターンを考える必要がありそうです。

次のステップとして小数点を許可する場合も、同様に、マッチ条件を考える必要があると
思うのですが。

"1.0.0.0" などという入力までマッチさせていいのか、そういうのは入力として来ないの
で考えなくていいのかでパターンが変わってくると思います。

[ 親 85005 / □ Tree ] 返信 編集キー/

▲[ 85008 ] / ▼[ 85021 ] ▼[ 85024 ] ▼[ 85030 ]
■85014 / 2階層)  Re[2]: 正規表現の考え方がわかりません
□投稿者/ 夜叉丸 (71回)-(2017/09/05(Tue) 12:49:24)
No85008 (WebSurfer さん) に返信
> ■No85005 (夜叉丸 さん) に返信
>
> 文字列の条件を明確にしていただかないとなかなかレスしずらいです。
>
最初は Rectangle ra です。
Match m = new Regex(@"{X=(?<X>[-]*\d+),Y=(?<Y>[-]*\d+),Width=(?<Width>[-]*\d+),Height=(?<Height>[-]*\d+)}").Match(ra.ToString());
これだと取得することができました。

わからないのは RectangleF ra になります。
0になってしまいます。
[ 親 85005 / □ Tree ] 返信 編集キー/

▲[ 85014 ] / 返信無し
■85021 / 3階層)  Re[3]: 正規表現の考え方がわかりません
□投稿者/ WebSurfer (1294回)-(2017/09/05(Tue) 15:07:03)
No85014 (夜叉丸 さん) に返信

> 最初は Rectangle ra です。

それを聞いているのではなく、正規表現の話なので、対象となる文字列がどうなるのか
を聞いています。

たぶん、Rectangle というのは System.Drawing.Rectangle 構造体のことで、ToString
メソッドで得られる文字列を対象としているのでははないかと想像してます。

Rectangle の方は X, Y, Width, Height いずれも Int32 型ということで、ToString が
どういう結果になるかはたぶん想像の範囲に収まるでしょうけど、RectangleF の方はど
うなるのでしょう?

自分が探した限りですが、RectangleF.ToString() がどういう結果になるかを書いた
Microsoft の公式文書見つかりませんでした。

#MSDN ライブラリには "この Rectangle 構造体の位置、幅、および高さが含まれた文字
列 (例 : {X=20, Y=20, Width=100, Height=50})" と書いてありましたが、そもそもそれ
も間違っているし・・・

なので、実際に試してその結果から想像するしかなさそうです。

それを回答者が行うのではなく、質問者さんの方で調べて質問者さんの言葉で書いていた
だきたかったのですが。
[ 親 85005 / □ Tree ] 返信 編集キー/

▲[ 85014 ] / ▼[ 85025 ]
■85024 / 3階層)  Re[3]: 正規表現の考え方がわかりません
□投稿者/ WebSurfer (1295回)-(2017/09/05(Tue) 15:53:15)
No85014 (夜叉丸 さん) に返信

ちょっとだけ調べてみましたが、

new RectangleF(20f, -20.856f, 100.123456789f, 50.9f);
 ↓↓
{X=20,Y=-20.856,Width=100.1235,Height=50.9}

という結果から、指数形式になることはない、数字として変な形(1.0.0 とか ---1 とか)
になることはない・・・とすれば、数字のところは「ハイフン、数字、ピリオドが一文字
以上」という条件のみでよさそうです。

であれば、以下のようにしてできると思います。

Rectangle re = new Rectangle(20, -20, 100, 50);
Console.WriteLine(re.ToString());
RectangleF rf = new RectangleF(20f, -20.856f, 100.123456789f, 50.9f);
Console.WriteLine(rf.ToString());

Regex regex = new Regex(@"
    ^                   # 開始のアンカー
    {X=                 # {X= という文字列で始まる 
    (?<X>[-0-9.]+)      # X という名前付グループ。ハイフン、数字、ピリオドが一文字以上
    ,Y=                 # ,Y= という文字列が来る
    (?<Y>[-0-9.]+)      # Y という名前付グループ。ハイフン、数字、ピリオドが一文字以上
    ,Width=             # ,Width= という文字列が来る
    (?<Width>[-0-9.]+)  # Width という名前付グループ。ハイフン、数字、ピリオドが一文字以上
    ,Height=            # ,Height= という文字列が来る
    (?<Height>[-0-9.]+) # Height という名前付グループ。ハイフン、数字、ピリオドが一文字以上
    }                   # } で終わる
    $                   # 終了のアンカー",
    RegexOptions.IgnorePatternWhitespace);

Match m = regex.Match(re.ToString());
GroupCollection g = m.Groups;
Console.WriteLine("X=" + g["X"].Value + ",Y=" + g["Y"].Value + 
    ",Width=" + g["Width"].Value + ",Height=" + g["Height"].Value);

m = regex.Match(rf.ToString());
g = m.Groups;
Console.WriteLine("X=" + g["X"].Value + ",Y=" + g["Y"].Value +
    ",Width=" + g["Width"].Value + ",Height=" + g["Height"].Value);

/*
結果は:
{X=20,Y=-20,Width=100,Height=50}
{X=20,Y=-20.856,Width=100.1235,Height=50.9}
X=20,Y=-20,Width=100,Height=50
X=20,Y=-20.856,Width=100.1235,Height=50.9
*/

[ 親 85005 / □ Tree ] 返信 編集キー/

▲[ 85024 ] / ▼[ 85026 ]
■85025 / 4階層)  Re[4]: 正規表現の考え方がわかりません
□投稿者/ Hongliang (565回)-(2017/09/05(Tue) 16:03:53)
> という結果から、指数形式になることはない、数字として変な形(1.0.0 とか ---1 とか)
> になることはない・・・とすれば、数字のところは「ハイフン、数字、ピリオドが一文字
> 以上」という条件のみでよさそうです。

指数形式になりえますし、NaNも正負の無限大も出現しえますよ。
個々の浮動小数点数値はSingle::ToStringしてるだけですね。
https://referencesource.microsoft.com/#System.Drawing/commonui/System/Drawing/Advanced/RectangleF.cs
// CurrentCultureを使ってるので、小数点記号が "," の可能性とかも考える?
[ 親 85005 / □ Tree ] 返信 編集キー/

▲[ 85025 ] / ▼[ 85028 ]
■85026 / 5階層)  Re[5]: 正規表現の考え方がわかりません
□投稿者/ WebSurfer (1296回)-(2017/09/05(Tue) 17:16:00)
No85025 (Hongliang さん) に返信

> 指数形式になりえますし、NaNも正負の無限大も出現しえますよ。
> 個々の浮動小数点数値はSingle::ToStringしてるだけですね。

> CurrentCultureを使ってるので、小数点記号が "," の可能性とかも考える?

RectangleF 構造体に設定された X. Y, Width, Height を ToString するという場合は NaN や
正負無限大は考えなくてもよさそうだと思いますが、指数は、

RectangleF rf = new RectangleF(20f, -20.856f, 100.123456789f, .0000023f);

というようなことをすると(実際にそういう設定が有るかどうかはさておき)、

{X=20,Y=-20.856,Width=100.1235,Height=2.3E-06}

になってしまいますね。

小数点も fr-FR とかですと '.' ではなく ',' になるようですし。

RectangleF.ToString に限れば、数字の部分の文字列を取得できれば良いわけで、どういう文
字列になるかは気にする必要はないわけですから、確かに No85016 の Hongliang さんの案が
現実的だと自分も思います。
[ 親 85005 / □ Tree ] 返信 編集キー/

▲[ 85026 ] / ▼[ 85128 ]
■85028 / 6階層)  Re[6]: 正規表現の考え方がわかりません
□投稿者/ 魔界の仮面弁士 (1403回)-(2017/09/05(Tue) 18:47:55)
No85026 (WebSurfer さん) に返信
> ■No85025 (Hongliang さん) に返信
> 確かに No85016 の Hongliang さんの案が現実的だと自分も思います。

同じく一票。

元の RectangleF.ToString で得た値が、小数表記でも指数表記でも非数値(NaN)や無限大でも
float.Parse/.TryParse で問題なく復元できるので、コードも比較的単純になります。
(ToString 時のカルチャと TryParse 時のカルチャを合致させる必要はありますが)


<蛇足>
Rectangle → String → Rectangle な変換が目的であれば、
型コンバーター(RectangleConverter クラス)を使えないかと思ったのですが、
ToString の場合とは書式が異なりますし、RectangleF には使えないので断念…。
</蛇足>
[ 親 85005 / □ Tree ] 返信 編集キー/

▲[ 85028 ] / ▼[ 85131 ]
■85128 / 7階層)  Re[7]: 正規表現の考え方がわかりません
□投稿者/ 夜叉丸 (78回)-(2017/09/12(Tue) 11:49:52)
No85028 (魔界の仮面弁士 さん) に返信
> ■No85026 (WebSurfer さん) に返信
>>■No85025 (Hongliang さん) に返信
>>確かに No85016 の Hongliang さんの案が現実的だと自分も思います。
>
> 同じく一票。
>

X=(?<X>.+?) と X=(?<x>.+) は結果的に同じなのでしょうか?
? があるのとないのとでの違いが判りません。
結果は同じのように見えますが

最終的に
X=???,Y=???,Width=???,Height=???
にて、??? を取りたかっただけなので
X=(?<X>.+?) や X=(?<x>.+) で取り込めました
??? は int または float の文字列なので
float.Parse() でとれば 値は取得することが可能だと思います。

[ 親 85005 / □ Tree ] 返信 編集キー/

▲[ 85128 ] / 返信無し
■85131 / 8階層)  Re[8]: 正規表現の考え方がわかりません
□投稿者/ 魔界の仮面弁士 (1416回)-(2017/09/12(Tue) 12:11:56)
No85128 (夜叉丸 さん) に返信
> X=(?<X>.+?) と X=(?<x>.+) は結果的に同じなのでしょうか?
前者のグループ名は "X" ですが、
後者のグループ名は "x" ですね。

> ? があるのとないのとでの違いが判りません。
(?<X>何某) の方の "?" だとしたら、グループ名をつけるためのものです。
.+? の方の "?" だとしたら、最短一致を意味します。

string text = "X=12,Y=34,Y=56,Z=78";
var m1 = Regexes.Match(text, "Y=(?<y>.+?)");
var m2 = Regexes.Match(text, "Y=(?<y>.+)");
var m3 = Regexes.Match(text, "Y=(?<y>[^,]+)");


たとえば上記の場合、下記の結果となります。

m1[0].Groups["Y"].Captures[0].Value == "3"
m1[1].Groups["Y"].Captures[0].Value == "5"
m2[0].Groups["Y"].Captures[0].Value == "34,Y=56,Z=78"
m3[0].Groups["Y"].Captures[0].Value == "34"
m3[1].Groups["Y"].Captures[0].Value == "56"
[ 親 85005 / □ Tree ] 返信 編集キー/

▲[ 85014 ] / ▼[ 85122 ]
■85030 / 3階層)  Re[3]: 正規表現の考え方がわかりません
□投稿者/ WebSurfer (1297回)-(2017/09/05(Tue) 19:27:28)
No85014 (夜叉丸 さん) に返信

Rectangle.ToString とか RectabgleF.ToString で得られた文字列から正規表現を使って X, Y, Width,
Height を取り出す必要性があるかというと、.NET アプリの世界に限れば全く完全に 100% ないと思うの
ですが・・・

プロパティとして X, Y, Width, Height が提供されているのですから、それを使えばいいのですから。

このような質問をしたのはどういう理由でしょう。教えていただけませんか? > 夜叉丸さん
[ 親 85005 / □ Tree ] 返信 編集キー/

▲[ 85030 ] / ▼[ 85123 ] ▼[ 85130 ]
■85122 / 4階層)  Re[4]: 正規表現の考え方がわかりません
□投稿者/ 夜叉丸 (76回)-(2017/09/12(Tue) 10:20:13)
No85030 (WebSurfer さん) に返信

>
> プロパティとして X, Y, Width, Height が提供されているのですから、それを使えばいいのですから。
>
> このような質問をしたのはどういう理由でしょう。教えていただけませんか? > 夜叉丸さん

Rectangle や Size を ToString() で出力されたテキスト(CSV)ファイルがあります。
このデータを自分で作ったプログラムの取り込みたいだけなのですが、
width とか , とか = で Index を使ってやろうとしていたのですが、調べていると Match というのがあるとわかって
利用しようと思ったのですが、正規表現が理解できなくて取得がうまくできなかったのです。

string 等のプロパティで X, Y, Width, Height があるのでしょうか?
それとも、ParseExact のような形で取得できるのでしょうか?



[ 親 85005 / □ Tree ] 返信 編集キー/

▲[ 85122 ] / ▼[ 85124 ]
■85123 / 5階層)  Re[5]: 正規表現の考え方がわかりません
□投稿者/ Hongliang (567回)-(2017/09/12(Tue) 10:38:53)
> string 等のプロパティで X, Y, Width, Height があるのでしょうか?
> それとも、ParseExact のような形で取得できるのでしょうか?

出力するときに単に
writer.WriteLine("{0},{1}", id, rect);
みたいに書き込むのではなく、
writer.WriteLine("{0},{1},{2},{3},{4}", id, rect.X, rect.Y, rect.Width, rect.Height);
みたいに出力しておけば、いちいち解析しなくて済んだって話ですね。
すでに前者のようなデータが存在する状況では今更な話ではあります。
[ 親 85005 / □ Tree ] 返信 編集キー/

▲[ 85123 ] / 返信無し
■85124 / 6階層)  Re[6]: 正規表現の考え方がわかりません
□投稿者/ 夜叉丸 (77回)-(2017/09/12(Tue) 10:48:04)
No85123 (Hongliang さん) に返信

> すでに前者のようなデータが存在する状況では今更な話ではあります。

おっしゃる通りです。
でも、私もやってしまうかもしれませんね。ToString って簡単に文字列にしてくれるし
[ 親 85005 / □ Tree ] 返信 編集キー/

▲[ 85122 ] / 返信無し
■85130 / 5階層)  Re[5]: 正規表現の考え方がわかりません
□投稿者/ WebSurfer (1301回)-(2017/09/12(Tue) 12:11:35)
No85122 (夜叉丸 さん) に返信

Hongliang さんのレスとダブるところがありますが・・・

> Rectangle や Size を ToString() で出力されたテキスト(CSV)ファイルがあります。

既存の「テキスト(CSV)ファイル」があって、それを作るのは質問者さんの責任範囲外、
かつ、作る人にこのように作ってくれと注文を出せる立場にもないのであれば、今回の話
のように正規表現を使って抜き出すというのはやむを得ないと思います。

そうではなくて、質問者さんが「テキスト(CSV)ファイル」の作成方法が指定できるので
あれば、正規表現など使わなくても取得できるように、最初から「テキスト(CSV)ファイル」
の形式を考えておくべきと思います。
[ 親 85005 / □ Tree ] 返信 編集キー/

▲[ 85005 ] / ▼[ 85015 ]
■85010 / 1階層)  Re[1]: 正規表現の考え方がわかりません
□投稿者/ 魔界の仮面弁士 (1402回)-(2017/09/05(Tue) 10:57:21)
2017/09/05(Tue) 11:36:37 編集(投稿者)

No85005 (夜叉丸 さん) に返信
> ra.ToString() = "{X=3, Y=6, Width=9, Height=12}"
> Match m = new Regex(@"{X=(?<X>[-]*\d+),Y=(?<Y>[-]*\d+),Width=(?<Width>[-]*\d+),Height=(?<Height>[-]*\d+)}").Match(ra.ToString());

これではヒットしないと思いますよ。元の文字列が
"{X=3, Y=6, Width=9, Height=12}" ではなく
"{X=3,Y=6,Width=9,Height=12}" であったのなら、
m.Groups["X"] で拾えるでしょうけれども。

カンマの後に空白を許容したいのであれば、
"," ではなく ", " や ",\s*" に変更してみてください。


> int ix = (int.TryParse(m.Groups["X"].ToString(), out ix)) ? ix : 0;
false 判定時には 0 が出力される仕様なので、三項演算子を使わずに
 int ix; int.TryParse(m.Groups["X"].ToString(), out ix);
あるいは
 int ix; int.TryParse(m.Groups["X"].Value, out ix);
でも OK ですね。


> この場合
> "3" = "(?<X>[-]*\d+)" であらわされるということですよね。
元の文字列に空白が含まれていなければ "3" になると思います。


> [-] 連続した文字範囲の1文字 : あるかもしれないしないかもしれないマイナスフラグ
"[-]" は "-" と同義で、それ自体は単なる - 記号です。


> * 直前の文字が0回以上繰り返す。 : なので先頭だから繰り返さないので0回以上?
すなわち、"X=---3" のような文字列に対してもヒットします。
この場合、--- 部がキャプチャされて m.Groups["X"].Value == "---3" となります。

もしも「符号があるかもしれないし無いかもしれない」にしたいのであれば、
"[+-]?" の方が良いかもしれません。


> \d 0から9までの数字       : 数字を使用
半角の "3" だけでなく
全角の "3" にもヒットします。


> ところが同様にfloat の場合どうすればよいのかわかりません。
単純には
 [+-]?[0-9]+[.]?[0-9]([eE][+-])?[0-9]
などが思い当たります。

float 値として float.NaN や float.NegativeInfinity が含まれる場合にも
対処が必要なら、もう一ひねり必要かも知れません。


// RectangleF r = new RectangleF(float.Epsilon, float.NaN, float.NegativeInfinity, float.PositiveInfinity);
// string rs = r.ToString();
[ 親 85005 / □ Tree ] 返信 編集キー/

▲[ 85010 ] / ▼[ 85016 ]
■85015 / 2階層)  Re[2]: 正規表現の考え方がわかりません
□投稿者/ 夜叉丸 (72回)-(2017/09/05(Tue) 13:55:07)
No85010 (魔界の仮面弁士 さん) に返信
> 2017/09/05(Tue) 11:36:37 編集(投稿者)

>>ra.ToString() = "{X=3, Y=6, Width=9, Height=12}"
>>Match m = new Regex(@"{X=(?<X>[-]*\d+),Y=(?<Y>[-]*\d+),Width=(?<Width>[-]*\d+),Height=(?<Height>[-]*\d+)}").Match(ra.ToString());
>
> これではヒットしないと思いますよ。元の文字列が
> "{X=3, Y=6, Width=9, Height=12}" ではなく
> "{X=3,Y=6,Width=9,Height=12}" であったのなら、
> m.Groups["X"] で拾えるでしょうけれども。

Rectangle ra = new Rectangle(3,6,9,12);
です。確認したら"{X=3,Y=6,Width=9,Height=12}"でした。

> 単純には
>  [+-]?[0-9]+[.]?[0-9]([eE][+-])?[0-9]
> などが思い当たります。
例外はハンドルされていませんとなります。
System.ArgumentException:'解析中 "{X~(?<X>[+-]?[0-9]+.]?[0-9]([eE]・・・・・

RectangleF raf = new RectangleF(3f, -6.2f, 9.3f, 12.4f);
Match f = new Regex(@"{X=(?<X>[+-]?[0-9]+[.]?[0-9]([eE][+-])?[0-9])," +
"Y=(?<Y>[+-]?[0-9]+[.]?[0-9]([eE][+-])?[0-9])," +
"Width=(?<Width>[+-]?[0-9]+[.]?[0-9]([eE][+-])?[0-9]))," +
"Height=(?<Height>[+-]?[0-9]+[.]?[0-9]([eE][+-])?[0-9]))}").Match(raf.ToString());

[ 親 85005 / □ Tree ] 返信 編集キー/

▲[ 85015 ] / ▼[ 85017 ]
■85016 / 3階層)  Re[3]: 正規表現の考え方がわかりません
□投稿者/ Hongliang (563回)-(2017/09/05(Tue) 14:13:03)
突き詰めると面倒なので、入力がRectangleF::ToString()であるという前提であれば、
{X=(?<x>.+),Y=(?<y>.+),以下略}
のように割り切ってしまうのも手かと思います。
[ 親 85005 / □ Tree ] 返信 編集キー/

▲[ 85016 ] / ▼[ 85019 ]
■85017 / 4階層)  Re[4]: 正規表現の考え方がわかりません
□投稿者/ 夜叉丸 (73回)-(2017/09/05(Tue) 14:28:52)
No85016 (Hongliang さん) に返信
> 突き詰めると面倒なので、入力がRectangleF::ToString()であるという前提であれば、
> {X=(?<x>.+),Y=(?<y>.+),以下略}
> のように割り切ってしまうのも手かと思います。


"[-]*\w+.*\w?"でやってみたらいけました。
これですべて賄えるのかわかりませんが・・・


それと[.+]だけでなぜいけるのか全く分かりません。
これでいけるのなら
Match m1 = new Regex(@"{X=(?<X>+),Y=(?<Y>+),Width=(?<Width>+),Height=(?<Height>+)}").Match(ra.ToString());
これもいけそうな気がするのですが・・・いけませんでした。


[ 親 85005 / □ Tree ] 返信 編集キー/

▲[ 85017 ] / ▼[ 85020 ]
■85019 / 5階層)  Re[5]: 正規表現の考え方がわかりません
□投稿者/ ペイビン (2回)-(2017/09/05(Tue) 14:37:36)
(?<Y>+) の括弧の中は
単に、1個の+文字にマッチする、という意味ですよ。

[ 親 85005 / □ Tree ] 返信 編集キー/

▲[ 85019 ] / ▼[ 85022 ] ▼[ 85023 ]
■85020 / 6階層)  Re[6]: 正規表現の考え方がわかりません
□投稿者/ 夜叉丸 (74回)-(2017/09/05(Tue) 14:49:32)
No85019 (ペイビン さん) に返信
> (?<Y>+) の括弧の中は
> 単に、1個の+文字にマッチする、という意味ですよ。
> 
ますます、わからなくなってきました。[+] が [.+] になると [.+]かどうかの判断にならずに、フロート型数値文字列をとれるようになるのでしょうか?

また Rectangle ra = new Rectangle(1, 12, 234, 4); としてマイナスがない状態なのに
Match m = new Regex(@"{X=(?<X>[-]*\w+,Y=(?<Y>[-]*\w+,Width=(?<Width>[-]*\w+),Height=(?<Height>[-]*\w+)}").Match(ra.ToString());
これがいけて次のがいけなくなる理由もわかりません
Match m1 = new Regex(@"{X=(?<X>*\w+),Y=(?<Y>*\w+),Width=(?<Width>*\w+),Height=(?<Height>*\w+)}").Match(ra.ToString());

[-]はマイナスフラグを取得するためのものではないのでしょうか?
と、同時に[\w+]は文字をとってくるための手段ではないってことですか?

\w で1文字とってきて、\w+ は連続した文字をとってくるという認識が崩れてしまいました。
例えば "ABC" の3文字をとる場合、 ~\w\w\w" でも "\w+" でも取得できると思っていたのですが・・・



[ 親 85005 / □ Tree ] 返信 編集キー/

▲[ 85020 ] / 返信無し
■85022 / 7階層)  Re[7]: 正規表現の考え方がわかりません
□投稿者/ shu (1053回)-(2017/09/05(Tue) 15:10:29)
No85020 (夜叉丸 さん) に返信

VB.NETソースですが
RectangleF.ToString()の結果であれば


        Dim rf As New RectangleF(CSng(TextBox1.Text), CSng(TextBox2.Text), CSng(TextBox3.Text), CSng(TextBox4.Text))
        Dim re As New Regex("(?<Column>\w+)=(?<Val>[^,}]+)[,}]")   <--- 最後は *?)[,}]でも大丈夫かも。
        For Each m In re.Matches(rf.ToString).OfType(Of Match)
            Console.WriteLine($"{m.Groups("Column")} = {m.Groups("Val")}")
        Next

こんな感じでどうでしょう?

[ 親 85005 / □ Tree ] 返信 編集キー/

▲[ 85020 ] / ▼[ 85027 ]
■85023 / 7階層)  Re[7]: 正規表現の考え方がわかりません
□投稿者/ Hongliang (564回)-(2017/09/05(Tue) 15:43:55)
正規表現においては、[ ] は特別な文字です。なので、文中に紛れると正規表現的な意味の [ ] なのか単に文字列を強調するためのものなのか区別がつかなくなります。
ここでは二重引用符 "" で文字列を強調することにします。"." であれば、正規表現中に . と記述することを意味します。

> [+] が [.+] になると [.+]かどうかの判断にならずに、フロート型数値文字列をとれるようになるのでしょうか?

"+" は、「直前の文字が1回以上出現する」にマッチします。
が、"(?<a>+)" と記述した場合、 "(?<a>" の部分は文字ではなくグループ化およびグループ名のためのものであり、文字ではありません。
なので、「直前の文字」が存在せず正規表現の解析時に実行時例外になるでしょう。

"." は、「任意の1文字」にマッチします。
".+" とすると、「「任意の1文字」が1回以上出現する」にマッチすることになります。

なお、"[+]" は、まず "[ ]" によって、「その中のいずれかの文字」にマッチすることになります。
"[ ]" の内部では "+" のような普段の正規表現中では特殊な文字も、普通の文字として扱われます。
なので、"[+]" は、「"+" のいずれかの文字」、つまり "+" にマッチすることになります。

> また Rectangle ra = new Rectangle(1, 12, 234, 4); としてマイナスがない状態なのに
> Match m = new Regex(@"{X=(?<X>[-]*\w+,Y=(?<Y>[-]*\w+,Width=(?<Width>[-]*\w+),Height=(?<Height>[-]*\w+)}").Match(ra.ToString());
> これがいけて次のがいけなくなる理由もわかりません
> Match m1 = new Regex(@"{X=(?<X>*\w+),Y=(?<Y>*\w+),Width=(?<Width>*\w+),Height=(?<Height>*\w+)}").Match(ra.ToString());

"*" は「直前の文字が0回以上出現する」にマッチします。
しかし "+" のときと同じく、"(?<X>" が文字ではないので、その直後に "*" を置くことはできません。

> [-]はマイナスフラグを取得するためのものではないのでしょうか?

最初の正規表現ではマイナス符号を取得するためのものですね。
"[ ]" で囲む意味はないし、* だと2つ以上連続していても許されてしまう問題がありますが。

> と、同時に[\w+]は文字をとってくるための手段ではないってことですか?

"\w+" は、アルファベット・数字・アンダースコアのみで作られている部分文字列にマッチさせるものです。
正規表現では "[a-zA-Z_0-9]+" と等価ですね。

> \w で1文字とってきて、\w+ は連続した文字をとってくるという認識が崩れてしまいました。
> 例えば "ABC" の3文字をとる場合、 ~\w\w\w" でも "\w+" でも取得できると思っていたのですが・・・

先の投稿で「いけませんでした」とだけ書かれていますが、単にマッチしなかったのと、正規表現の解析失敗による実行時例外をごっちゃにしていませんか?
例えば
new Regex(@"{X=(?<X>*\w+)")
は、先ほども言ったように "*" の前に文字がないので、不正な正規表現となり、実行時例外が発生します。
これは "\w" が何にマッチするか以前の話です。
[ 親 85005 / □ Tree ] 返信 編集キー/

▲[ 85023 ] / ▼[ 85121 ]
■85027 / 8階層)  Re[8]: 正規表現の考え方がわかりません
□投稿者/ ペイビン (3回)-(2017/09/05(Tue) 18:20:05)
2017/09/05(Tue) 18:25:09 編集(投稿者)

≪パターンを修正しました≫
僕なら、すべてを正規表現に頼ろうとせず、パターンを
"{X=(?<X>.+?),\s*Y=(?<Y>.+?),\s*Width=(?<Width>.+?),\s*Height=(?<Height>.+?)}"
のようにして、X, Y, Width, Heightに割り当てられる内容を後で吟味して
rectを求めます。
なお、「.+?」は、「.+」の最短マッチと言います。
例えば、検索テキスト文字列が"{X=0, Y=0, Width=0, Height=0}あいうえおかきくけこ{X=1, Y=2, Width=3, Height=4}さしすせそ"
のような場合で、複数のマッチを検索したい場合は、この最短マッチの概念が必要となりますが、
必要に応じ調べてください。

ところで、検索したいテキストは、
X, Y, Width, Heightの順序は固定なのですよね?
恐らく、今回のケースでは、"{X=1, Y=2, Width=3, Height=4}"
のパターンで事足りるのだろうと思いますが、
もし、{Y=2, X=1, Height=4, Width=3}のようなパターンがあり得るなら、
これも考慮する必要があります。
[ 親 85005 / □ Tree ] 返信 編集キー/

▲[ 85027 ] / 返信無し
■85121 / 9階層)  Re[9]: 正規表現の考え方がわかりません
□投稿者/ 夜叉丸 (75回)-(2017/09/12(Tue) 09:43:41)
No85027 (ペイビン さん) に返信

> ところで、検索したいテキストは、
> X, Y, Width, Heightの順序は固定なのですよね?
> 恐らく、今回のケースでは、"{X=1, Y=2, Width=3, Height=4}"
> のパターンで事足りるのだろうと思いますが、
> もし、{Y=2, X=1, Height=4, Width=3}のようなパターンがあり得るなら、
> これも考慮する必要があります。

もともと保存される文字列は
Rectangle の ToString() での文字列です。
なので、X, Y, Width, Height だと私は思っています。

[ 親 85005 / □ Tree ] 返信 編集キー/


管理者用

- Child Tree -