이게 나를 당황하게 만든다
다음과 같이 항상 추가해야 하는 변수가 있는 큰 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[[:>:]]