을 사용하여 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
답변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를 사용하고 있는 것 같습니다.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
답변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