none
改行含むの正規表現 RRS feed

  • 質問

  •  お世話になっていおります。
     C言語のコメントを取り除く処理を考えています。先ず、/*~*/の部分を正規表現で消したいと思います。
               myRegex = new Regex(@"/\*[\s\S]*\*/");
               string After = myRegex.Replace(str, "");
     をしたら、最初の/* と最後の*/の間の内容が全て消えてしまいました。
     例: 下記の内容に対して実施すると、A()関数の部分も消えてしまいます。
        どう表現したらよいでしょうか
      /*****
         xxxxxxxx
         xxxxxxxx
       **********/
       int A(){
        bbb
       }
      /*****
         xxxxxxxx
         xxxxxxxx
       **********/
       int B()
       {
         nnn
       }
           
    2009年8月1日 6:48

回答

  • この例の場合、改行を含むことは関係ありません。
    /* abc */ def /* ghi */ と1行になっていてもこの問題が発生し、defが消えます。
    具体的には、正規表現は最長一致を採用しているため、ソースコードの文脈に関係なく、1つ目のコメント開始(/*)~最後のコメント終了(*/)に一致したまでです。

    対策は2つあります。
    1. 中間部分の条件として「コメント終了」を含まないようにする
      Regex.Replace( str, @"/\*(?:[^*]|\*(?!/))*\*/" );
      *以外か、/が後続しない*という条件です。
    2. 最長一致ではなく最短一致させる
      Regex.Replace( str, @"/\*.*?\*/", RegexOptions.Singleline );
      最短一致なので、*/が見つかったらすぐに終了します。
    なお、[\s\S]よりもRegexOptions.Singlelineを付けた.の方がお勧めです。
    実際C#には影響ないとは思いますが、以前[\s\S]だか[\w\W]だかが「全ての文字」にマッチしない正規表現エンジンがありました。
    • 回答としてマーク 章Z 2009年8月1日 11:41
    2009年8月1日 10:18

すべての返信

  • この例の場合、改行を含むことは関係ありません。
    /* abc */ def /* ghi */ と1行になっていてもこの問題が発生し、defが消えます。
    具体的には、正規表現は最長一致を採用しているため、ソースコードの文脈に関係なく、1つ目のコメント開始(/*)~最後のコメント終了(*/)に一致したまでです。

    対策は2つあります。
    1. 中間部分の条件として「コメント終了」を含まないようにする
      Regex.Replace( str, @"/\*(?:[^*]|\*(?!/))*\*/" );
      *以外か、/が後続しない*という条件です。
    2. 最長一致ではなく最短一致させる
      Regex.Replace( str, @"/\*.*?\*/", RegexOptions.Singleline );
      最短一致なので、*/が見つかったらすぐに終了します。
    なお、[\s\S]よりもRegexOptions.Singlelineを付けた.の方がお勧めです。
    実際C#には影響ないとは思いますが、以前[\s\S]だか[\w\W]だかが「全ての文字」にマッチしない正規表現エンジンがありました。
    • 回答としてマーク 章Z 2009年8月1日 11:41
    2009年8月1日 10:18
  • この例の場合、改行を含むことは関係ありません。
    /* abc */ def /* ghi */ と1行になっていてもこの問題が発生し、defが消えます。
    具体的には、正規表現は最長一致を採用しているため、ソースコードの文脈に関係なく、1つ目のコメント開始(/*)~最後のコメント終了(*/)に一致したまでです。

    対策は2つあります。
    1. 中間部分の条件として「コメント終了」を含まないようにする
      Regex.Replace( str, @"/\*(?:[^*]|\*(?!/))*\*/" );
      *以外か、/が後続しない*という条件です。
    2. 最長一致ではなく最短一致させる
      Regex.Replace( str, @"/\*.*?\*/", RegexOptions.Singleline );
      最短一致なので、*/が見つかったらすぐに終了します。
    なお、[\s\S]よりもRegexOptions.Singlelineを付けた.の方がお勧めです。
    実際C#には影響ないとは思いますが、以前[\s\S]だか[\w\W]だかが「全ての文字」にマッチしない正規表現エンジンがありました。

      佐祐理さん、迅速な返信で、有難う御座いました。早速、教えて頂いた方法で、試しました。完璧にコメントの削除ができました。
      有難うございました。正規表現敷居の高さを改めて実感しました。
    2009年8月1日 11:53