으로 grep
, 나는 패턴과 일치하는 모든 행을 선택하려면, 그것은 또 다른 패턴과 일치하지 않습니다. 옵션 (또는 , 또는 )을 grep
사용할 수 있도록 단일 호출을 사용할 수 있기를 원합니다 .--after-context
--before-context
--context
-v
옵션 을 grep
사용하여 전달하는 모든 패턴을 무효화하므로 여기에서 실행 가능하지 않습니다 -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
답변
GNU grep 을 가지고 있다면 부정 구조 를 가진 Perl 정규 표현식을 사용할 수 있습니다 .
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}
'
답변
GNU grep을 사용하고있는 것 같습니다 . GNU grep을 사용하면 --perl-regex
플래그를 전달하여 PCRE를 활성화 한 다음 아래 예와 같이 네거티브 미리보기 어설 션을 제공 할 수 있습니다.
grep --after-context=1 \
--perl-regex '^(?:(?!ignore me).)*needle(?:(?!ignore me).)*$' file.txt
four needle
five
노트의 중요한 것은 여기 즉 (?:(?!STRING).)*
이다 STRING
로 [^CHAR]*
하는 것입니다CHAR
답변
멀티 라인 IO를 더 잘 처리하므로 awk를 대신 사용하는 것이 좋습니다. 어느 1) 파이프의 GNU AWK에 결과 --\n
기록 세퍼레이터, 또는 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