VB.NETで正規表現を使用した検索でフリーズする
- VB.NET(2003)ですが、Regexを使った正規表現での検索時に検索パターンによっては、プログラムがフリーズして固まります。なにか情報はないでしょうか?
- VBプログラムファイル内のコメントを一気に検索するつもりで、 (".*?"|[^"'])*('.*?)\r\n とするとOKですが、 (".*?"|[^"']+)('.*?)\r\n とするとフリーズします。(+を一つ足した)
- フリーズは、pMatches.Countの部分で起こっているようです。Matchesの変わりにMatchとNextMatchを使うと、順に検索結果が得られますが、最後の結果にNextMatchを実行したところで固まります。
- ベストアンサー
VB.NET で正規表現を使用した検索でフリーズする
VB.NET(2003)ですが、Regexを使った正規表現での検索時に検索パターンによっては、プログラムがフリーズして固まります。なにか情報はないでしょうか? VBプログラムファイル内のコメントを一気に検索するつもりで、 (".*?"|[^"'])*('.*?)\r\n とするとOKですが、 (".*?"|[^"']+)*('.*?)\r\n とするとフリーズします。(+を一つ足した) プログラムは、 pMatches = Regex.Matches(src, pat) If pMatches.Count = 0 Then MsgBox("マッチしません") End If といった感じで、 src=対象テキストを全行取込んだ文字列、pat=検索パターンです。 フリーズは、pMatches.Countの部分で起こっているようです。 Matchesの変わりにMatchとNextMatchを使うと、順に検索結果が得られますが、最後の結果にNextMatchを実行したところで固まります。 フリーズ中、タスクマネージャで見ている限りではCPU=100%(HTでは50%)、となりますが、使用メモリー量は変化ありません。
- bikkuri
- お礼率37% (3/8)
- Visual Basic
- 回答数2
- ありがとう数2
- みんなの回答 (2)
- 専門家の回答
質問者が選んだベストアンサー
いやいや、バックトラッキングを甘く見ちゃいけないと思いますよ。 (a+)* という正規表現では、対象の文字列が一文字増えるたびにパタンの数が 2 倍になります。 手元で軽く実験して見ました。 (a+)*b という正規表現に対して、文字列 aaa....aaac を検索させると、a が 20 文字のときで約 1 秒、21 文字で約 2 秒、22 文字で約 4 秒、23 文字で約 8 秒、24 文字で約 15 秒でした。 それに対し、(a)*b という正規表現では a が 1000 文字でも 1 秒掛かりませんでした。 実際、(a+)*b のパタン数は a が 24 文字のとき 2 の 24 乗で 16777216 通りですが、(a)*b の方は 1000 文字でも 1001 * 1002 / 2 で 501501 通りしかありません。 ちなみに、(?>(a+)*b) のようにバックトラッキングを無効にすると、数千文字でも一瞬でした。
その他の回答 (1)
- UKY
- ベストアンサー率50% (604/1207)
例えば、(a)*b という正規表現に対し aaac という文字列を検索させると、次のように処理が進みます。 (a)(a)(a)c (a)(a)ac (a)aac aaac * 演算子や + 演算子は繰り返しの回数を変化させて可能性のあるパタンを全て試します。上の例では繰り返しの回数は 4 パタンあります。 正規表現が (a)*b ではなく (a+)*b だと、次のようになります。 (aaa)c (aa)(a)c (aa)ac (a)(aa)c (a)(a)(a)c (a)(a)ac (a)aac aaac + を足しただけで可能性のあるパタンの数が増えています。ソースコードのように何千文字もある文字列を検索すれば、パタンの数は莫大になります。つまり、検索処理が半永久的に終わらなくなるのです。
補足
回答ありがとうございます。 「処理時間が非常にかかっている」というもの十分考えられるとおもいますが、今回の検索パターンではバックトラックはあまり発生しないと思いますので、それほどの時間はかからないはずと思います。(勝手な思い込みかもしれませんが) また、Matchで検索結果を順番に取得した場合、最後の検索結果までは特に問題なく実行できます。 フリーズするのは、最後のその次をNextMatchで取得する時に発生しているようです。 プログラムでは次のような感じです。 dim ma as match = Regex.Match(src, pat) do while ma.Success xxxxx ma = ma.NextMatch loop 最後の次をNextMatchで取得するとSuccess=Falseになっているはずですが、これを取得するタイミングで戻ってきません。 いくつかの対象テキストで試しましたが、このタイミングは同じでした。 (数行程度のテキストでは確かにOKでした。しかし30行程度でもNGです) 具体的なテキストとプログラムがあったほうが良さそうなので、用意してみます。
関連するQ&A
- カンマ区切りの金額を検索するための、正規表現を教えてください
PHP4を使っています。 表題のとおりなのですが、 カンマ区切りの金額を検索するための、正規表現を教えていただけないでしょうか? http://oraclesqlpuzzle.hp.infoseek.co.jp/regex/regex-3-14.html を参考に、 $pattern = '^(0|([1-9][0-9]{0,2}(,[0-9]{3}){0,2}))$'; if (preg_match("/$pattern/", $oneline_buffer, $matches)){ としているのですが、 なぜかpreg_matchにひっかかりません。 (preg_match の直前の行を通っていることは、確認済みです) どなたか、お助け願えれば幸いです。
- ベストアンサー
- PHP
- VB.NETの正規表現の検索を教えてください。
VB.NETの正規表現で文章中(HTMLソース)から番号を抜き取りたいのですが、 先頭の1つだけしか見つけられません。 htmlソース内に 番号:10000 番号:20000 番号:30000 番号:40000 という文字があるので、その後半の10000や20000を取得したいです。 下記のコードで実行すると、10000が4つ出力されてしまいます。 良い方法をご教示頂きたいです。よろしくお願いいたします。 Dim pagedata As String <---htmlソース Dim reg As Regex reg = New Regex("番号:(?<datano>.+)", RegexOptions.Compiled) Dim DataNo As String m = reg.Match(pagedata) While m.Success = True DataNo = reg.Match(pagedata).Result("${datano}") m = m.NextMatch() Console.WriteLine(DataNo) End While
- ベストアンサー
- Visual Basic
- 時間の正規表現
正規表現で、17:00:00という文字の17:00(時:分)の部分だけを見て、時間として認識させたいのですが、どのように記述すればいいのでしょうか? 以下のプログラムを作成したのですが、なぜかfalseが返されてしまって困っています。 教えてください。宜しくお願いいたします。 String str_time = "17:00:00"; String str = "([0-9]|([0-1][0-9]|[2][0-3]))[:][0-5][0-9]"; Pattern pat = Pattern.compile( str ) ; Matcher mat = pat.matcher( str_time ) ; if( mat.matches() ){ // 処理 }
- ベストアンサー
- Java
- .NET のスマートな正規表現の記述の仕方
VB8 (2005)で、正規表現の書き方ですが、抽出する場合は、 以下のようにしましたが、抽出せず、単にマッチしたかとうが If文で判別する方法が知りたいです。 Imports System.Text.RegularExpressions '正規表現 Dim dat As String = "TEST 01" Dim ptn As String 'パターン Dim r As Regex ' Dim dv As String '部分 '抽出 ptn = "^TEST ([0-9]+)$" r = New Regex(ptn, RegexOptions.IgnoreCase) For Each m As Match In r.Matches(dat) dv = m.Groups(1).Value() MsgBox("抽出=[" & dv & "]") Next あと、上のようにFor文で回していますが、Globalでなく、今回は1つだけの抽出で、しかも1つだけの()なので、これをFor文を使わずに直接取得する書き方はあるのでしょうか? それ以前に、.NETの正規表現の書き方が一般的でなければ、ご指導お願い致します。
- ベストアンサー
- Visual Basic
- WSHの正規表現について
WindowsXPのCACLSコマンドの出力結果(テキストにリダイレクト)に改行や復帰が入っていて、空行の削除をしたいのです。 下記のプログラムを作ったのですが、復帰コードが 入っている箇所がとれないのです。どなたかご教授お願い致します。。。 Set fso = CreateObject("Scripting.FileSystemObject") Set src = fso.GetFolder("C:\WORK") Set regEx1 = New RegExp srhStr1 = "^ *$" regEx1.Pattern = srhStr1 regEx1.Global = True regEx1.IgnoreCase = True Set TextFile = fso.OpenTextFile("cacls結果.txt") Do Until TextFile.AtEndOfStream tmpLine = TextFile.ReadLine If regEx1.Test(tmpLine) Then else srhLine = srhLine & tmpLine & vbNewLine End If Loop WScript.Echo srhLine
- ベストアンサー
- その他(プログラミング・開発)
- 正規表現について
パターンマッチのところでつまずいてしまっています。 例えば、 マッチがマッチをすったらマッチになった という文面があったとします。(適当です) $txt = 'マッチがマッチをすったらマッチになった'; if($txt =~ m/$txt/s){$txtb = $';} print "$txtb"; としたら、 がマッチをすったらマッチになった と出てくると思います。 これを、 になった と表示させる為に、最後の「マッチ」にパターンマッチをさせる方法はありませんでしょうか? ネット上のHPを検索しましたが、どうしても見つけられませんでした。 何とぞ宜しくお願いします。
- ベストアンサー
- Perl
- 正規表現を教えてください。
正規表現を教えてください。 C#で正規表現を用いた文字列検索を勉強中なのですが、うまくマッチさせることができません。教えていただけないでしょうか。 検索対象の文字列は下のようになります。 キーワード;値; 文字列中に該当するキーワードが存在する場合に、その値を取得するプログラムを考えています。しかし、私の正規表現では2つ目の「;」を検出してしまい、キーワードのみを取得することが出来ずに困っています。 見当違いの表記をしているとは思うのですがどなたかお助けください。 match = Regex.Match(line, "^(.*);"); C#初心者なものです。
- ベストアンサー
- Microsoft ASP
- VB.NETで正規表現を教えてください。URL文字を取得
VB.NETなのですが、 htmlソースを変数に入れて、その中からURLを抽出して、 1つずつ保存していくという動作をさせたいのですが、 どうしてもURLを一つずつ取得することができません。 Dim r As Regex Dim m As Match Dim JpgFile As String r = New Regex("http://.+\.jpg") m = r.Match(html) If m.Success = False Then Else JpgFile = m.Value ここで1つずつ保存 End If 現在、ここまで出来たのですが、 これだと、変数html内に複数のjpgのURLがあると 最初のURLの1文字目から、最後のURLの末尾までを一度に 取得してしまいます。 URLの文字列はhttp://で始まっていて、終わりは・・・.jpg" になっていたり、"がなかったりします。 >で閉じる前に同じタグ内にWidthなどサイズを指定している場合もあります。 また、上記のようにタグ内に書かれていなくて、クリッカブルリンクになっていないURLの場合もありそれも取得したいです。 一つずつ取得する方法や一度に配列に読み込む方法などがありましたら、 ご教示頂けると助かります。 よろしくお願い致します。
- ベストアンサー
- Visual Basic
- VB2005のRegexで全角文字のマッチ
VB2005のRegexで、インターネットのソースコードを取得し”次の10件"というキーワードの位置を取得しようとしていますが、どうもソースコードの時点で、全角文字(2バイト文字)が認識されていないようです。どうすれば、マッチできるでしょうか?教えてください。 仮に、下記のルーチンに、Debug.Print(inputString)を入れて表示させてみると、全角の表示がされていません。 よろしくお願いいたします。 Sub DumpHrefs(ByVal inputString As String) Dim r1 As Regex Dim m1 As Match r1 = New Regex("次の10件≫") m1 = r1.Match(inputString) While m1.Success Debug.WriteLine("次の10件" & " at " & m1.Groups(1).Index.ToString()) m1 = m1.NextMatch() End While End Sub
- 締切済み
- Visual Basic
- VB.NETの正規表現をVBAで記述するには
VB2010.NETのコードをExcel2010のVBAのコードに置き換える作業をしていますが、List1のようにVB.NETのコードには、Inports System.Text.RegularExpressions で.NET正規表現パッケージが使われて、この部分をVBAではどのように記述すればよいのでしょうか。 自分なりにList2のようにしてみましたが、Dim M As MatchのMatchの部分で「ユーザ定義型は定義されていません」というコンパイルエラーが発生します。 参照設定にはSystem.Text.RegularExpressionsが見当たりませんが何を指定すればよいのでしょうか。 Microsoft VBScript Regular Expressions 5.5のRegExpオブジェクトでは後読みができないので大変困っています。 よろしくお願いします。(Windows7) ---List1:VB.NET(正常)--------------- Option Explicit On Option Strict On Imports System.Text.RegularExpressions Module Module1 Sub Main() Dim SampleText As String = "今日は西暦2014年6月20日です" Dim M As Match = Regex.Match(SampleText, "(?<=西暦)\d+") If Not M.Success Then Console.WriteLine("no match") Else Dim MatchedText As String = M.Value Dim MatchedFrom As Integer = M.Index Dim MatchedLen As Integer = M.Length MsgBox("matched [" & MatchedText & "]" & _ " from char#" & MatchedFrom.ToString() & _ " for " & MatchedLen.ToString() & " chars.") End If End Sub End Module ---List2:VBA(このコードではエラーになる)----- Option Explicit Sub test() Dim SampleText As String Dim M As Match Dim R As New Regex Dim MatchedText As String Dim MatchedFrom As Integer Dim MatchedLen As Integer SampleText = "今日は西暦2014年6月20日です" R = Regex("(?<=西暦)\d+") M = R.Match(SampleText) If Not M.Success Then MsgBox ("no match") Else MatchedText = M.Value MatchedFrom = M.Index MatchedLen = M.Length MsgBox("matched [" & MatchedText & "]" & _ " from char#" & MatchedFrom.ToString() & _ " for " & MatchedLen.ToString() & " chars.") End If End Sub ------------------------------------------
- ベストアンサー
- Excel(エクセル)
お礼
どうも甘く見ていたようです。 「ちなみ・・」のように (?>(".*?"|[^"']+))*('.*?)\r\n や (".*?"|(?>[^"']+))*('.*?)\r\n とすると検索できました。 よく考えると、パターンそのものは、テキストの先頭から最後のコメント部分までは全部、最長での一致範囲なのでバックトラックが発生しないが、最後のコメントからテキスト末尾にパターンが一致しないことを判定するのにバックトラックが発生して長考しているようです。 (".*?"|[^"']+)*(('.*?)\r\n|$) としてもフリーズしませんでした。 もうちょっと細部を確認したいので、来週まで保留にさせてください。
補足
perlでも実行して同様にフリーズすることを確認しました。 「バックトラックで長考している」で納得できました。 (?> ..)などで回避するようにします。 回答ありがとうございました。