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

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

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

Re[4]: 正規表現が理解できません.


(過去ログ 129 を表示中)

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

■76249 / inTopicNo.1)  正規表現が理解できません.
  
□投稿者/ よぽん (38回)-(2015/06/18(Thu) 15:31:19)

分類:[.NET 全般] 

タイトル通りですけど、正規表現が理解できません。

たとえば
Rectangle ra = new Rectangle(1, 2, 3, 4);
string s = ra.ToString(); ← s = "{X=1,Y=2,Width=3,Height=4}"

このような文字列から Rectangle を求めるのに以下のようにすれば良いとわかりました。

Match m = new Regex(@"(?<x>\w+),Y=(?<y>\w+),Width=(?<w>\w+),Height=(?<h>\w+)}").Match(value.ToString());
int ix = (int.TryParse(m.Groups["x"].ToString(), out ix)) ? ix : 0;
int iy = (int.TryParse(m.Groups["y"].ToString(), out iy)) ? iy : 0;
int iw = (int.TryParse(m.Groups["w"].ToString(), out iw)) ? iw : 0;
int ih = (int.TryParse(m.Groups["h"].ToString(), out ih)) ? ih : 0;
Value = new Rectangle(ix, iy, iw, ih);

でも、結局正規表現の説明がされているところを見つけることができないので

private void button1_Click(object sender, EventArgs e)
{
string s = "SUM(A1*B2)";

Match m = new Regex(@"SUM((?<x>\w+)*(?<y>\w+))").Match(s);
string ix0 = m.Groups["x"].ToString();
string iy0 = m.Groups["y"].ToString();

MessageBox.Show("[" + ix0 + "][" + iy0 + "]");

m = new Regex(@"SUM((?<x1>\w+)(?<y1>\w+)*(?<x2>\w+)(?<y2>\w+))").Match(s);
string ix1 = m.Groups["x1"].ToString();
string iy1 = m.Groups["y1"].ToString();
string ix2 = m.Groups["x2"].ToString();
string iy2 = m.Groups["y2"].ToString();

MessageBox.Show("[" + ix1 + "][" + iy1 + "][" + ix2 + "][" + iy2 + "]");

}

どちらも値をとってきません。

どうすればよいのでしょうか?
また、正規表現の使い方で詳しく優しい説明が書かれているところ
どこかに有りませんでしょうか?

引用返信 編集キー/
■76250 / inTopicNo.2)  Re[1]: 正規表現が理解できません.
□投稿者/ WebSurfer (599回)-(2015/06/18(Thu) 15:53:24)
No76249 (よぽん さん) に返信

目的は、

(1) 正規表現の勉強をすることで、Rectangle.ToString で得られる文字列を
  使ったのはその一例に過ぎない、または、

(2) Rectangle 構造体の位置、幅、および高さを取得したい(手段は問わない)

のどっちなんですか?
引用返信 編集キー/
■76251 / inTopicNo.3)  Re[2]: 正規表現が理解できません.
□投稿者/ 774RR (267回)-(2015/06/18(Thu) 16:13:58)
(1) なら
MSDN の説明で十分理解できると思うのだけど
https://msdn.microsoft.com/ja-jp/library/cc392020.aspx
https://msdn.microsoft.com/ja-jp/library/az24scfc.aspx
定番のところで
http://dobon.net/vb/dotnet/string/regex.html

(2) なら、オイラより C# 詳しい人にお任せってことで。
引用返信 編集キー/
■76252 / inTopicNo.4)  Re[1]: 正規表現が理解できません.
□投稿者/ WebSurfer (600回)-(2015/06/18(Thu) 17:31:31)
No76249 (よぽん さん) に返信

たぶん (1) だと想像して、自分が「正規表現の使い方で詳しく優しい説明が書かれて
いる」と思う記事を紹介しておきます。

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

なぜパターン @"SUM((?<x>\w+)*(?<y>\w+))" が "SUM(A1*B2)" にマッチしないかという
と、文字 (, *, ) がメタ文字(上に紹介した記事参照)だからでしょう。パターンの方
のそれらの文字を [] で囲うとうまく行くと思います。お試しください。
引用返信 編集キー/
■76253 / inTopicNo.5)  Re[1]: 正規表現が理解できません.
□投稿者/ WebSurfer (601回)-(2015/06/18(Thu) 19:52:36)
No76249 (よぽん さん) に返信

【追伸】

[] で囲うより、\ でエスケープした方がスマートかもしれません。
引用返信 編集キー/
■76272 / inTopicNo.6)  Re[2]: 正規表現が理解できません.
□投稿者/ よぽん (39回)-(2015/06/19(Fri) 14:11:30)
No76250 (WebSurfer さん) に返信

> (1) 正規表現の勉強をすることで、Rectangle.ToString で得られる文字列を
>   使ったのはその一例に過ぎない、または、
>
> (2) Rectangle 構造体の位置、幅、および高さを取得したい(手段は問わない)
>
> のどっちなんですか?

もちろん(1)です。

元々は(2)で文字列でSubstringやらIndexOfを使って長いコード書いていました。
けど、正規表現が理解できて使えるようになったら楽になるかなって、
それに知らないより知っていた方がいいじゃない。
引用返信 編集キー/
■76273 / inTopicNo.7)  Re[2]: 正規表現が理解できません.
□投稿者/ よぽん (40回)-(2015/06/19(Fri) 14:34:29)
最初からもうすでに躓いています。

量指定子ですが
1.*: "0 回以上の繰り返し回数" を表します。
2.+: "1 回以上の繰り返し回数" を表します。
3.?: "0 または 1 回の繰り返し回数" を表します。

パターン
fo* ⇒ foo、foe、food、fooot、"forget it"、funny、puffy
fo+ ⇒ foo、foe、food、foot、"forget it"
fo? ⇒ foo、foe、food、foot、"forget it"、funny、puffy

となっていますが、意味が分かりません。

0回以上、≧0 だとしたら、
fo* はどのような文字列も一致してしまいますよね。
と、いうことは

0回以上、>0 と考えれば
fo* は fo があれば一致 でも、な時funny, puffy が一致するの?
それにどんな時でも fo* = fo? になってしまいますよね。
fo? はいらないんじゃないですか?




引用返信 編集キー/
■76274 / inTopicNo.8)  Re[2]: 正規表現が理解できません.
□投稿者/ よぽん (41回)-(2015/06/19(Fri) 14:48:44)
No76253 (WebSurfer さん) に返信
> [] で囲うより、\ でエスケープした方がスマートかもしれません。

ごめんなさい、おっしゃってる意味がよくわかりません

string ix1 = m.Groups["x1"].ToString(); ⇒ string ix1 = \x1;

のようなことでしょうか?
引用返信 編集キー/
■76275 / inTopicNo.9)  Re[3]: 正規表現が理解できません.
□投稿者/ Hongliang (320回)-(2015/06/19(Fri) 14:52:15)
> 0回以上、≧0 だとしたら、
> fo* はどのような文字列も一致してしまいますよね。

fが存在しない文字列には一致しませんが。

> 0回以上、>0 と考えれば

*は0回以上なのでこの解釈は誤りです。
+が1回以上を表しますね。

> それにどんな時でも fo* = fo? になってしまいますよね。
> fo? はいらないんじゃないですか?

fo?dとfo*dでは、foodがマッチするかどうかで明確に違いが現れますね。
fdとfodはマッチして欲しいがfoodはマッチして欲しくない、ってときに*ではどうにもなりません。
引用返信 編集キー/
■76276 / inTopicNo.10)  Re[3]: 正規表現が理解できません.
□投稿者/ 774RR (268回)-(2015/06/19(Fri) 15:06:55)
正規表現のわかりにくいのは
1.「文字列の始まりと終わり」と「マッチの始まりと終わり」が違うこと
2.「文字列がマッチする」という文言は「文字列の途中からマッチしてもマッチという」こと
  (先頭から一致とかそういう指定をしていないとき)
あたりだろうか。

https://msdn.microsoft.com/ja-jp/library/ms972966.aspx
の例を解説するなら

fo* の * が係るのは [直前の] 1文字だから o のみ。ということで
1. f で始まって(マッチが始まって)
2. o の0回以上の繰り返し
ということ。
だから「マッチパターン」は f fo foo foooo ... となる。文字列の中にこれがあれば「マッチした」だ。
文字列の先頭からマッチするのが food (最短マッチなら f 最長マッチなら foo となる)
文字列の途中からマッチするのが puffy (最短でも最長でも f のみマッチで、マッチ2回)

fo+ や fo? も解説してあげられるけどもう一度自分で考えてみて。
引用返信 編集キー/
■76277 / inTopicNo.11)  Re[3]: 正規表現が理解できません.
□投稿者/ WebSurfer (603回)-(2015/06/19(Fri) 15:10:58)
No76273 (よぽん さん) に返信
> 最初からもうすでに躓いています。
>
> 量指定子ですが
> 1.*: "回数" を表します。
> 2.+: "1 回以上の繰り返し回数" を表します。
> 3.?: "0 または 1 回の繰り返し回数" を表します。
>
> パターン
> fo* ⇒ foo、foe、food、fooot、"forget it"、funny、puffy
> fo+ ⇒ foo、foe、food、foot、"forget it"
> fo? ⇒ foo、foe、food、foot、"forget it"、funny、puffy
>
> となっていますが、意味が分かりません。

*, +, ? は 文字列 fo に対して働くと勘違いしていませんか? そうではなくて、
上の「パターン」の例では o という文字に対して働きます。


> 0回以上、≧0 だとしたら、
> fo* はどのような文字列も一致してしまいますよね。

なので、パターン fo* は、対象文字列の中のどこか(最初である必要はない)に f と
いう文字があって、その直後に o という文字が 0 回以上の繰り返しある文字列にマッ
チします。

fo+ も fo? も同様に考えれば納得できるのでは?
引用返信 編集キー/
■76278 / inTopicNo.12)  Re[3]: 正規表現が理解できません.
□投稿者/ くーへん (4回)-(2015/06/19(Fri) 15:12:45)
No76273 (よぽん さん) に返信
> 最初からもうすでに躓いています。
>
> 量指定子ですが
> 1.*: "0 回以上の繰り返し回数" を表します。
> 2.+: "1 回以上の繰り返し回数" を表します。
> 3.?: "0 または 1 回の繰り返し回数" を表します。
>
> パターン
> fo* ⇒ foo、foe、food、fooot、"forget it"、funny、puffy
> fo+ ⇒ foo、foe、food、foot、"forget it"
> fo? ⇒ foo、foe、food、foot、"forget it"、funny、puffy
>
> となっていますが、意味が分かりません。
>
> 0回以上、≧0 だとしたら、
> fo* はどのような文字列も一致してしまいますよね。
> と、いうことは
>
> 0回以上、>0 と考えれば
> fo* は fo があれば一致 でも、な時funny, puffy が一致するの?
> それにどんな時でも fo* = fo? になってしまいますよね。
> fo? はいらないんじゃないですか?
>

http://www.rider-n.sakura.ne.jp/regexp/regexp.php

上記のサイトで、右下の「対象文字列」に、「foo」を入力し
右上の「パターン文字列」に

foo* を入力すると→ foo
fo* を入力すると→ foo
fo? を入力すると→ fo

が、赤くなり、fo?だけ(完全一致の場合)違いが出ます。

「正規表現ハンドブック」
ISBN4-7973-2850-9
は、結構わかりやすかかったですよ。
http://www.sbcr.jp/products/4797328509.html

正規表現を知っておくと、エディターで不要な文字を削除したり
置換したり出来るので便利です。

以上
引用返信 編集キー/
■76279 / inTopicNo.13)  Re[2]: 正規表現が理解できません.
□投稿者/ よぽん (42回)-(2015/06/19(Fri) 15:15:52)
No76252 (WebSurfer さん) に返信
> なぜパターン @"SUM((?<x>\w+)*(?<y>\w+))" が "SUM(A1*B2)" にマッチしないかという
> と、文字 (, *, ) がメタ文字(上に紹介した記事参照)だからでしょう。パターンの方
> のそれらの文字を [] で囲うとうまく行くと思います。お試しください。

string str = "SUM(A1*B2)";

固定部分は"SUM(", "*", ")" なので

Match m = new Regex(@"SUM(??*??)").Match(str);
↑ ↑
            ここを指定すればよいのかな?

ここでは A1 ですが、エクセル同様 AB34 とかもあり得るので

(?<x>\w+) で最初の英字部分をとって次 (?<x>\w+) で
数字をとってくれればと考えました。
けど、その前に "SUM(??*??)" の (と)はメタ文字(予約文字みたいなもの?)
らしいので、[] で囲う?なので

"SUM([?][?]*[?][?]\)" にしてから、
Match m = new Regex(@"SUM([(?<x>\w+)][(?<x>\w+)]*[(?<x>\w+)][(?<x>\w+)\)]").Match(str);
追加情報:解析中 "SUM([(?<x>\w+)][(?<x>\w+)]*[(?<x>\w+)][(?<x>\w+))]" - ) が足りません。
やっぱりうまくいかない

[]を使う
Match m = new Regex(@"SUM((?<x>\w+)(?<x>\w+)][*](?<x>\w+)(?<x>\w+))]").Match(str);
\を使うのかな?
Match m = new Regex(@"SUM\((?<x>\w+)(?<x>\w+)]*(?<x>\w+)(?<x>\w+)\)]").Match(str);
いずれにしても
うまく動作しません。

引用返信 編集キー/
■76280 / inTopicNo.14)  Re[3]: 正規表現が理解できません.
□投稿者/ WebSurfer (604回)-(2015/06/19(Fri) 15:20:17)
No76274 (よぽん さん) に返信
> ■No76253 (WebSurfer さん) に返信
>>[] で囲うより、\ でエスケープした方がスマートかもしれません。
>
> ごめんなさい、おっしゃってる意味がよくわかりません
>
> string ix1 = m.Groups["x1"].ToString(); ⇒ string ix1 = \x1;
>
> のようなことでしょうか?

いえ、Match m = new Regex(@"SUM((?<x>\w+)*(?<y>\w+))").Match(s); の Regex の引数
に使っているパターンのことです。

具体的には、

@"SUM((?<x>\w+)*(?<y>\w+))" ⇒ @"SUM[(](?<x>\w+)[*](?<y>\w+)[)]" または @"SUM\((?<x>\w+)\*(?<y>\w+)\)"

のようにするということです。

さらに、必ず SUM で始まって ) で終わるなら @"^SUM\((?<x>\w+)\*(?<y>\w+)\)$" のよう
にした方がいいです。
引用返信 編集キー/
■76300 / inTopicNo.15)  Re[4]: 正規表現が理解できません.
□投稿者/ よぽん (43回)-(2015/06/22(Mon) 12:50:34)
ありがとうございます。
取得できるようになりました。

string str = "SUM(A1*B2)";

//Match m = new Regex(@"SUM[(](?<x>\w+)[*](?<y>\w+)[)]").Match(str);
Match m = new Regex(@"SUM\((?<x>\w+)\*(?<y>\w+)\)").Match(str);

string sx = m.Groups["x"].ToString();
string sy = m.Groups["y"].ToString();

MessageBox.Show("[" + sx + "][" + sy + "]");


解決済み
引用返信 編集キー/


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

このトピックに書きこむ

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

管理者用

- Child Tree -