特定の末尾文字なしで特定の文字列に一致する正規表現

特定の末尾文字なしで特定の文字列に一致する正規表現

これは私を戸惑う

次のように常に追加する必要がある変数を持つ大きなCソースファイルがあります。

CycleCounter += SomeValue

一部の値は重要ではありません。

数千行のソースファイルには、このような数百行のコードがあります。すべての割り当てが追加され、予期しない割り当てまたは減算が行われるように努めています。

「+」またはいくつかのスペースと「+」が後に来ないすべてのCycleCounterエントリを探したいです。

私は次のような表現を試してみました。

CycleCounter\s*[^+]

ただし、この場合は「+」が表示される場所も一致します。

これはケース1とも一致しますが、後続の「+」なしでケース2と3のみを一致させたいです。

if (postbyte & 0x80)
{
    switch (postbyte & 0x1F)
    {
    case 0: // Post inc by 1
        ea = (*xfreg16[Register]);
        (*xfreg16[Register])++;
        CycleCounter+=NatEmuCycles21; // good. expression correctly ignored this
        break;

    case 1: // post in by 2
        ea = (*xfreg16[Register]);
        (*xfreg16[Register]) += 2;
        CycleCounter += NatEmuCycles32; // good. expression incorrectly identified 
        break;

    case 2: // pre dec by 1
        (*xfreg16[Register]) -= 1;
        ea = (*xfreg16[Register]);
        CycleCounter -= NatEmuCycles21;  // mistake, subtracted. expression correctly identified
        break;

    case 3: // pre dec by 2
        (*xfreg16[Register]) -= 2;
        ea = (*xfreg16[Register]);
        CycleCounter = NatEmuCycles32; // mistake, assigned. expression correctly identified
        break;

    case 4: // no offset
        ea = (*xfreg16[Register]);
        break;

答え1

PCRE(Perl Compatible Regular Expressions)を使用している場合、このアドインは空白のないアイテムを貪欲に一致させ、空白の一致を防ぎます+。例えば。 PCRE(GNU grepオプション)を使用して行番号を表示するには、withを使用します。\s*[^+]grep-P-n

grep -Pn 'CycleCounter\s*+[^+]' file

別のPCRE:

grep -Pn 'CycleCounter(?!\s*\+)' file

今回は否定的な予測を使用して指定されますnot followed a '+' or some white space and a '+'


sed以下を使用して、出力から不要な行を削除できます。

sed '/CycleCounter/!d; /CycleCounter[[:space:]]*+/d; =' file

CycleCounterを含まない行を削除し、CycleCounterの後にスペースと「+」を含む行も削除します。=行番号を印刷します。

答え2

それは*量子についてです。\s*- これは、一致するものがない可能性があることを意味します。 2番目の式[^ +]は、単語の直後の空白文字と一致しますCycleCounter

grep 'CycleCounter\s\+[^+]'

または

grep 'CycleCounter\s*[^+]='

または

grep 'CycleCounter\s*[^+ ]'

答え3

CycleCounter前提を一致させたい場合いいえオプションのスペース sum の後に+Perl の否定予測演算子を使用できます。

grep -P 'CycleCounter(?!\s*\+)'

(これはPerlに似た正規表現をgrepサポートする実装を想定しています)。-P

CycleCounter後にオプションの空白と+空白も空白でもない文字が続く場合、一致させたい場合:

grep 'CycleCounter[[:space:]]*[^+[:space:]]'

[[:space:]]Perlと同じPOSIX正規表現です\s。一部の実装ではこれをBRE / EREの拡張としてgrepもサポートしていますが、または括弧内の式内の一致のPOSIX要件をサポートしていません。\s[\s]\s

いずれにせよ、[[:space:]]および\sは改行と一致しますが、デフォルトではgrep一度に1行の内容のみが処理されるため(改行区切り文字を除く)、両方とも次の最初の行と一致します。

   CycleCounter
     += 12;

例えば。

PCRE(Perlに似た正規表現を実装し、オプションをサポートするほとんどの実装で使用されるライブラリであるpcregrepPCREに付属)を使用すると、次のことができます。grep-P

pcregrep -M '(?s)CycleCounter(?!\s*\+).*?;'

ここでは-M、複数行モードを有効にし、改行でも一致を(?s)引き起こし、完全なC文が次の文字で印刷されるようにします。..*?;;

もちろん、まだ次のようなものに騙されます。

CycleCounter // blah ;
  += (c == ';')
  + 3;

また彼らはで一致することに注意して下さいMyCycleCounter2 += 3。これを防ぐには、周囲に単語境界演算子を追加するだけですCycleCounter。 Perlには同等のPOSIX正規表現はありませんが、\bCycleCounter\bいくつかのgrep実装ではまたは拡張をサポートして\bいます。\<CycleCounter\>[[:<:]]CycleCounter[[:>:]]

関連情報