문자열을 포함하지 않는 그렙 정규식


181

grepsyslog 파일을 확인 하기 위해 정규식 패턴 목록을 전달하고 있습니다. 이들은 일반적으로 IP 주소 및 로그 항목과 일치합니다.

grep "1\.2\.3\.4.*Has exploded" syslog.log

"1\.2\.3\.4.*Has exploded"루프에서 전달 하는 부분 과 같은 패턴 목록 이므로 "-v"를 전달할 수 없습니다.

위의 역을 수행하려고 혼란 스럽습니다. 특정 IP 주소와 오류가있는 NOT match line은 "! 1.2.3.4. * 폭발했습니다"는 1.2.3.4 이외의 다른 시스템에 대해 syslog 줄과 일치합니다. . 내가 있어야 일치하지에 IP를 포함 할 수 있습니다.

StackOverflor에서 다양한 유사한 게시물을 보았지만 사용할 수없는 정규식 패턴을 사용 grep합니다. 누구나 실례를 제공 할 수 있습니까 grep?

업데이트 : 이것은 이런 스크립트에서 발생합니다.

patterns[1]="1\.2\.3\.4.*Has exploded"
patterns[2]="5\.6\.7\.8.*Has died"
patterns[3]="\!9\.10\.11\.12.*Has exploded"

for i in {1..3}
do
 grep "${patterns[$i]}" logfile.log
done

당신은 의미합니까 때때로 패턴과 일치하기를 원하지만 다른 시간이 모든 것을 일치시킬 제외하고 특정 패턴? (이것은 이상한 요구 사항처럼 보이지만 무엇이든). 이 경우, 두 개의 서로 다른 패턴 목록을 반복하지 않겠습니까?
beerbajay

글쎄, 나는 정규식에 대해 잘 모른다. 모든 로깅 장치에 대해이 사실을 알고 싶지 않기 때문에 "폭발 했음"에 대해 grep하고 싶지 않습니다. 따라서 어떻게 든 "Has Exploded"및! 9.10.11.12에 대해 grep 할 수 있습니까?
jwbensley

Neil이 제안한 것처럼 한 진술에서 절대적으로 해야하는 경우 부정적인 전망이 있습니다. 내 의견을 참조하십시오.
beerbajay

@Neil의 답변에 따라 PCRE 스타일 정규 표현식 일치 및 부정적인 예측 어설 션을 사용하십시오 .PCRE의 patterns[3]="\!9\.10\.11\.12.*Has exploded"변경 patterns[3]="(?<!9\.10\.11\.12).*Has exploded"grep "${patterns[$i]}" logfile.log변경 grep -P "${patterns[$i]}" logfile.log은 기본적으로 더 많은 메타 문자를 가정하므로 일부 이스케이프는 다른 일치하는 표현식에서 제거해야 할 수도 있습니다.
Codex24

답변:


341

grep일치, grep -v반대를 수행합니다. "A와 일치하지만 B와 일치하지 않아야"하는 경우 일반적으로 파이프를 사용합니다.

grep "${PATT}" file | grep -v "${NOTPATT}"

이것은 내가 언급 한 것처럼 루프의 중간에 들어가고 있으며 PATTERN을 grep에 전달하기 때문에 언급 한 것처럼 "-v"를 사용할 수 없습니다. PATTERN 목록을 반복하고 grep으로 전달하고 있습니다.
jwbensley

1
실제로 사용할 -v수 있으며 루프에서 사용할 수 있습니다. 아마도 당신은 당신의 한계에 대해 더 구체적이어야하거나, 당신의 스크립트가 어떻게 작동해야하는지에 대한 오해가있을 것입니다. 코드를 게시하십시오.
beerbajay

고마워 beerbajay, 나는 약간의 맥락을 제공하기 위해 원래 게시물에 스니핑 된 코드를 추가했습니다. 내가 무슨 뜻인지 알겠 니?
jwbensley

이 대답은 완전히 정확하지는 않지만 당신은 beerbajay를 거의 쓰지 않았습니다. 루프를 다시 생각하고 결국 -v를 사용해야했습니다. 포인터 주셔서 감사합니다;)
jwbensley 2016 년

1
그러나 A가 B로 구성되어 있다면 어떨까요? 즉, 내가 가진 라인에 맞게 어떤 것인지 전혀 AB와 선을? 파이프가 작동하지 않습니다.
pawamoy

15
(?<!1\.2\.3\.4).*Has exploded

부정적인 lookbehind (Perl regular expression)를 가지려면 -P로 이것을 실행해야하므로 명령은 다음과 같습니다.

grep -P '(?<!1\.2\.3\.4).*Has exploded' test.log

이 시도. 앞에 선행하는 행을 무시하려면 음수 비하인드를 사용합니다 1.2.3.4. 희망이 도움이됩니다!


1
나는 grep그것이 둘러보기를 지원하지 않는다고 확신합니다 . Gnu grep를 사용하지 않고 --P매개 변수를 사용하여 PCRE 엔진을 사용 하지 않는 한 .
Tim Pietzcker

grep은이 유형의 정규식을 지원하지 않습니다. $ grep -P (? <\! 1 \ .2 \ .3 \ .4) test.log -bash : 예기치 않은 토큰 근처 구문 오류`( '
jwbensley

쉘에 의해 해석 될 문자가 포함 된 정규식을 인용해야합니다.
beerbajay

올바른 인용 : grep -P '(?<!1\.2\.3\.4) Has exploded' test.loglookbehind는 표현식의 일치하는 부분 바로 앞에있는 문자에서만 작동하므로 주소와 메시지 사이에 다른 항목이 있으면 1.2.3.4 FOO Has exploded작동하지 않습니다.
beerbajay

@TimPietzcker, 매우 관찰자. 질문에 추가하겠습니다. 또한 .*그의 예가 가지고 있기 때문에 부정적인 전망이 뒤따른 다는 점에 유의하십시오 . 사이에 다른 텍스트가있을 수 있습니다.
Neil

2
patterns[1]="1\.2\.3\.4.*Has exploded"
patterns[2]="5\.6\.7\.8.*Has died"
patterns[3]="\!9\.10\.11\.12.*Has exploded"

for i in {1..3}
 do
grep "${patterns[$i]}" logfile.log
done

와 동일해야합니다

egrep "(1\.2\.3\.4.*Has exploded|5\.6\.7\.8.*Has died)" logfile.log | egrep -v "9\.10\.11\.12.*Has exploded"    
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.