

.NET4.5  
input = "abc123def$456ghi" (注 文字列、数字列ともランダムとします)  
において、先頭に$がない数字列を検出したく(123だけを検出したい)  
pattern = "(?\<!\$)\d+"  
で行うと、"123" , "56" となってしまいます。

どなたか、解法がわかるかた教えてください。  
また、正規表現だけでは無理だという回答でもいただけるとありがたいです。


CC BY-SA 3.0
2015-10-18T09:33:31.673
17768
2015-10-18T21:44:48.200
12830
question
.net 正規表現
正規表現　否定後読み　文字列中の数字列の先頭に'$'がない数字列の検出

[code]

    var pattern = @"(?<=[^$\d])\d+";
    
[/code]

のように肯定後読みで`$`もしくは数字ではない文字を探せばいいのではないでしょうか。ただこれでは文字列先頭の数字が含まれませんので、

[code]

    var pattern = @"(^|(?<=[^$\d]))\d+";
    
[/code]

と`^`も追加する必要があります。


CC BY-SA 3.0
2015-10-18T09:57:11.543
17770
2015-10-18T09:57:11.543
5750
17768
answer


質問文に「否定後読み」とありそれについてはpgrhoさんおよびunaristさんが答えられていますが、別解を。  
[.NET Frameworkの正規表現](https://msdn.microsoft.com/ja-
jp/library/e347654k\(v=vs.110\).aspx)がPerl、Python、Emacs、Tcl、JavaScriptなどと同じ従来型NFAエンジンであることを利用して

[code]

    var input = "abc123def$456ghi";
    var pattern = @"\$\d*|(\d+)";
    foreach(Match m in Regex.Matches(input, pattern)){
        if(m.Groups[1].Success)
            Console.WriteLine(m.Groups[1].Value);
    }
    
[/code]

で`"123"`を得ることができます。  
従来型NFAエンジンでは一致する限り取り込まれるので、`\$\d*`で`'$'`及びそれに続く数値を取り込みます。望ましくない`"$456"`はここでマッチし次に流れることはありません。そうでない場合に限り`(\d+)`にマッチしますので、これをグループでキャプチャします。  
ただし前半にマッチした場合でも全体では`m.Success`となっていますので、`m.Groups[1].Success`のみに絞り込みます。

正規表現エンジン自体の特性を理解していると、.NET
Framework以外にも応用が効きます。例えばJavaScriptの場合、後読みはありませんが私の挙げたパターンであれば表現できます。

* * *

「否定後読み」を使ったpgrhoさんおよびunaristさんのアプローチについても。

[code]

    var pattern = @"\d+(?<!\$\d+)";
    
[/code]

でもできます。こちらはまず数値、`"123"`と`"456"`との両方がマッチさせます。その上で`\$\d+`の否定後読みで`'$'`が先行している`"$456"`については除外し、結果的に`"123"`だけがマッチします。  
このパターンは正規表現の内容が人間にも読み易いものになっているかなと思います。（１文字ずつ否定後読みの確認をせずに済むため、たぶんパフォーマンス的にもいいはずです。）


CC BY-SA 3.0
2015-10-18T11:54:05.633
17774
2015-10-18T21:44:48.200
2015-10-18T21:44:48.200
4236
4236
17768
answer