0

C++ソースコードファイルから読み取った文字列でfor/if/whileキーワードを検索する正規表現を作成しようとしていますが、それらを含む単語は次のように除外します:

WhatifYes()
Whatfor()
Waitforwhile()

以下のように正規表現を書きました:

if { [ regexp {(for|while|if)(\s+)(\()} $lineValue ] } { 

しかし、次のようなケースは取り上げていません。

while(( int x = 0 ) > 0 );
while(( int x = 0 ) > 0 )
for(int y =0 ; ; )
for(int y =0 ; ; );
if( (int x = 9) > 0 )
if( (int x = 9) > 0 );

最初は、正規表現が次のようにフレーム化されていると思っていました。

if/for/while \s+ ( #space or multiple spaces

しかし、上記の例にスペースを含めてみました:

while (( int x = 0 ) > 0 );
while (( int x = 0 ) > 0 )
if ( (int x = 9) > 0 )
if ( (int x = 9) > 0 );

まだ正規表現が機能していません - それらをキャプチャするためにどの正規表現を使用すればよいか教えてください。

4

2 に答える 2

4

問題の一部は簡単に対処でき、一部は非常に困難です。

簡単な部分は、単語全体を確実に取得することです。\m制約エスケープは単語の最初でのみ一致し、\M制約エスケープは最後で一致するため、次を使用できます。

# Nothing capturing; you can add that as necessary
# Ellipsis for the bits I've not talked about yet
regexp {\m(?:while|if|for)\M\s*...} ...

非常に難しい部分は、括弧内の部分と一致しています。問題は、それが実際には(理論的な意味で)「言語」であり、一致する正規表現とは異なる種類のパーサー(つまり、で使用される有限オートマトンよりも複雑な状態モデルを持つ再帰下降パーサー)を必要とすることです。 REマッチング)。さらに、()これらの式で文字を使用するのが一般的です。代わりに、最も簡単なアプローチは、行の終わりにあり、セミコロンが続く可能性のある閉じ括弧と照合することですが、これは間違いなく正しくありません。あるいは、ネストされた親の限られた数のレベルをサポートすることも可能です。

# Match a few levels...
regexp {\m(?:while|if|for)\M\s*\((?:[^()]|\((?:[^()]|\([^()]*\))*\))*\)} ...

それでは、そのREを分解してみましょう。

\mワードスタート
(?:while | if | for)キーワードの1つ
\Mワードエンド
\s*オプションのスペース
\(オープンパレン
  (?: また...
    [^()]非親...
  | または...
    \(オープンパレン
      (?: また...
        [^()]非親...
      | または...
        \(オープンパレン
          [^()]*非親
        \)パレンを閉じる
      )*...上記の必要な数だけ
    \)パレンを閉じる
  )*...上記の必要な数だけ
\)パレンを閉じる

上記を見ると、パターンに気付くでしょう。はい、ネストを続けて、好きなだけ深くすることができます。あなたができないことは、REエンジンにあなたのためにその入れ子をさせることです。

于 2012-11-01T10:00:50.887 に答える
0

正規表現では、\s+ を使用しています。つまり、少なくとも 1 つのスペース/タブ/改行が必要です。\s* (0 個以上の空白) を使用し、前に来るものにロジックを追加します。

if { [ regexp {(^|[ \t])(for|while|if)(\s*)(\()} $lineValue ] } { 
于 2012-11-01T10:10:14.687 に答える