특정 후행 문자 없이 특정 문자열과 일치하는 정규식

특정 후행 문자 없이 특정 문자열과 일치하는 정규식

이게 나를 당황하게 만든다

다음과 같이 항상 추가해야 하는 변수가 있는 큰 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*- 이는 일치하는 항목이 없을 수 있음을 의미합니다. 두 번째 표현식 [^+]는 단어 바로 뒤의 공백 문자와 일치합니다 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기본적으로 한 번에 한 줄의 내용만 처리되므로(줄바꿈 구분 기호 제외) 둘 다 여전히 다음의 첫 번째 줄과 일치합니다.

   CycleCounter
     += 12;

예를 들어.

PCRE(펄과 유사한 정규 표현식을 구현하고 옵션을 지원하는 대부분의 구현에서 사용되는 pcregrep라이브러리인 PCRE와 함께 제공됨 )를 사용하면 다음을 수행할 수 있습니다.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[[:>:]]

관련 정보