grep을 사용하면 어떻게 패턴을 일치시키고 다른 패턴을 반전시킬 수 있습니까?

grep을 사용하면 어떻게 패턴을 일치시키고 다른 패턴을 반전시킬 수 있습니까?

를 사용하면 grep패턴과 일치하고 다른 패턴과 일치하지 않는 모든 줄을 선택하고 싶습니다. 옵션(또는 , 또는 )을 grep사용할 수 있도록 단일 호출을 사용할 수 있기를 원합니다 .--after-context--before-context--context

-vgrep옵션 을 사용하여 전달한 모든 패턴을 무효화하므로 여기서는 실행 가능하지 않습니다 -e.

다음 컨텍스트의 한 줄을 사용하여 일치하는 줄을 needle무시하고 일치하는 줄을 찾고 싶습니다 .ignore me

내 입력 파일은 다음과 같습니다.

one needle ignore me
two
three
four needle
five

내가 원하는 출력은 다음과 같습니다

four needle
five

보시다시피 이 순진한 솔루션은 작동하지 않습니다.

$ cat file | grep --after-context=1 needle | grep -v 'ignore me'
two
---
four needle
five

답변1

GNU grep이 있으면 다음을 사용할 수 있습니다.펄 정규 표현식, 이는부정 구조.

grep -A1 -P '^(?!.*ignore me).*needle'

GNU grep이 없으면 다음을 수행할 수 있습니다.awk에서 전후 컨텍스트 옵션을 에뮬레이트합니다..

awk -v after=3 -v before=2 '
/needle/ && !/ignore me/ {
    for (i in h) {
        print h[i];
        delete h[i];
    }
    until = NR + after;
}
{
    if (NR <= until) print $0; else h[NR] = $0;
    delete h[NR-before];
}
END {exit !until}
'

답변2

GNU를 사용하고 있는 것 같습니다.. GNU grep을 사용하면 플래그를 전달하여 --perl-regexPCRE를 활성화한 다음 아래 예와 같이 부정적인 예측 어설션을 제공할 수 있습니다.

grep --after-context=1 \
--perl-regex '^(?:(?!ignore me).)*needle(?:(?!ignore me).)*$' file.txt
four needle
five

여기서 주목해야 할 가장 중요한 점은 (?:(?!STRING).)*있는 STRING그대로 [^CHAR]*라는 것입니다.CHAR

답변3

여러 줄 IO를 더 잘 처리하므로 대신 awk를 사용하는 것이 좋습니다. 어느 하나1)--\n레코드 구분 기호를 사용 하여 결과를 GNU awk로 파이프하거나2)awk에서 모든 일치를 수행하십시오.

옵션 1

<file grep -A1 needle | awk '!/ignore me/' RS='--\n' ORS='--\n'

산출:

four needle                                                                                  
five
--

이 옵션은 전체 레코드에서 ignore me, 설정 FS=1및 일치 항목을 검색하여 $1첫 번째 줄과만 비교합니다.

옵션 2

<file awk 'a-- > 0; $0 ~ re1 && $0 !~ re2 { print $0; a=after }' re1=needle re2='ignore me' after=1

관련 정보