특정 문자열과 다음 줄을 포함하는 줄을 제거하십시오.


70

나는 이것을 사용한다

cat foo.txt | sed '/bar/d'

bar파일에 문자열 을 포함하는 줄을 제거 합니다.

그러나 그 줄 과 그 줄을 바로 뒤에 제거하고 싶습니다 . 가급적 sed이면 awk또는 MinGW32에서 사용할 수있는 다른 도구로 사용하십시오.

내가 얻을 수있는 것의 반대의 일종 grep으로 -A-B일치하는 행 다음 / 이전에 일치하는 라인뿐만 아니라 라인을 인쇄 할 수 있습니다.

그것을 달성하는 쉬운 방법이 있습니까?


2
정보를 얻으려면 : 항목이 두 줄짜리 로그를 분석하고 있습니다. 그래서 패턴과 일치하는 항목을 찾아서 다음 줄뿐만 아니라 제거하고 싶습니다. 따라서 연속 경기 라인을 처리 할 필요는 없지만 답변의 완전성에 감사드립니다!
jakub.g

답변:


74

GNU sed (포함되지 않은 Linux 또는 Cygwin)가있는 경우 :

sed '/bar/,+1 d'

bar연속 된 두 줄이 있으면 두 번째 줄을 분석하지 않고 삭제합니다. 당신이 3 선 파일이있는 경우 예를 들어, bar/ bar/ foofoo선은 유지됩니다.


1
길이에 +1 :) 내 특정 예에서는 연속 bars가 없으므로이 것이 매우 쉽게 기억됩니다.
jakub.g

11
sed '/bar/d'다음 문자열이 아닌 "특정 문자열을 포함하는 행 제거"를 원할 경우 .
AJP

수학 후 모든 줄을 제거하려면?
Pandya

1
@Pandya 그건 다릅니다. 예를 들어sed '/math/q'
Gilles

1
@AK 일치하는 줄을 삭제하려는 경우 훨씬 간단합니다.sed '/bar/d'
Gilles

16

bar연속 라인에서 발생할 수있는 경우 다음을 수행 할 수 있습니다.

awk '/bar/{n=2}; n {n--; next}; 1' < infile > outfile

일치하는 행을 포함하여 삭제할 행 수로 위의 2를 변경하여 두 개 이상의 행을 삭제하도록 조정할 수 있습니다.

그렇지 않은 경우는 쉽게에서 이루어집니다 sed@MichaelRollins '솔루션 또는 :

sed '/bar/,/^/d' < infile > outfile

AWK 솔루션의 또 다른 장점은로 바꿀 수 있다는 것 /bar/입니다 /bar|baz|whatever/. 에서 sed그 문법 작동하지 않습니다.
jakub.g

@ jakub.g, 나는 GNU sed를 가지고 있습니다 (v4.4). 다른 사람들에 대해서는 확실하지 않습니다. 내가 아는 것은 기본적으로 "기본"정규 표현식 구문을 사용한다는 것입니다. 이것이 귀하의 예제가 작동하지 않는 이유입니다. 원하는 것을 달성하기 위해 각 수직선 앞에 백 슬래시를 넣거나 sed"확장 된"정규식을 사용 하도록 요청할 수 있습니다. 자세한 내용은 gnu.org/software/sed/manual/html_node/…를 참조하십시오 . 이 사항도 적용됩니다 grep. 내 자신의 작업 예는 다음과 같습니다 echo $'0a\n1b\n2c' | sed '/0a\|1b/d'..
빅터 Yarema

12

나는 sed에 유창하지 않지만 awk에서는 그렇게하기 쉽습니다.

awk '/bar/{getline;next} 1' foo.txt 

awk 스크립트는 다음과 같이 읽습니다 : bar를 포함하는 줄의 경우, 다음 줄 (getline)을 얻은 다음 모든 후속 처리 (다음)를 건너 뜁니다. 마지막에 1 개의 패턴이 나머지 줄을 인쇄합니다.

최신 정보

의견에서 지적했듯이 위의 솔루션은 연속적으로 작동하지 않았습니다 bar. 수정 된 솔루션은 다음과 같습니다.

awk '/bar/ {while (/bar/ && getline>0) ; next} 1' foo.txt 

이제 모든 / bar / 줄을 건너 뛰기 위해 계속 읽습니다.


1
grep -A100 % 를 복제하려면 bar전체 블록을 제거한 후 1 행 후에 여러 개의 연속 행을 올바르게 처리해야합니다 .
jw013

7

이를 위해 sed의 스크립팅 기능을 사용하고 싶을 것입니다.

$ sed -e '/bar/ { 
 $!N
 d
 }' sample1.txt

샘플 데이터 :

$ cat sample1.txt 
foo
bar
biz
baz
buz

"N"명령은 다음 입력 행을 패턴 공간에 추가합니다. 패턴 일치 (/ bar /)의 행과 결합하면 삭제하려는 행이됩니다. 그런 다음 "d"명령을 사용하여 정상적으로 삭제할 수 있습니다.


콘솔에 줄 바꿈을 어떻게 입력합니까? 아니면 이것은 스크립트 전용입니까?
jakub.g

@ jakub.g : GNU sed와 함께 :sed -e '/bar/{N;d}' sample1.txt
Cyrus

2

일치하는 줄 바로 뒤에있는 줄을 제거해야하는 경우 sed프로그램은 연속적인 일치를 고려해야합니다. 다시 말해, 일치하는 행 다음에있는 행을 제거하면 그 뒤에 나오는 행도 제거해야합니다.

그것은 충분히 충분히 구현되었지만 약간 뒤 쳐야합니다.

printf %s\\n     0 match 2 match match \
                 5 6 match match match \
                 10 11 12 match 14 15  |
sed -ne'x;/match/!{g;//!p;}'

0
6
11
12
15

읽은 각 줄에 대해 보류 및 패턴 공간을 교환하여 작동하므로 매번 마지막 줄을 현재와 비교할 수 있습니다. 따라서 sed줄을 읽을 때 버퍼의 내용을 교환합니다. 이전 줄은 편집 버퍼의 내용이며 현재 줄은 보류 공간에 있습니다.

따라서 sed이전 행과 일치 match하는지 확인하고 !찾지 못하면 {함수 의 두 표현식 }이 실행됩니다. sedg등 패턴 영역 덮어 쓰기로 보류 공간 - 그것은 것이다 - 그리고 현재의 라인 홀드 패턴 공간 모두에서 다음을 의미 //가장 최근에 컴파일 된 정규 표현식에 일치 여부를 확인한를 - match- 그리고 경우는 그것을 하지 않습니다 match그것은 있다 printed.

이것은하지 않는 경우 선은 인쇄 의미 바로 이전 행은하지 않습니다 . 또한 일련의 es에 대한 불필요한 스왑을 포기합니다 .match matchmatch

이후에 발생하는 임의의 수의 줄을 삭제할 수있는 버전을 원한다면 match조금 더 많은 작업이 필요합니다.

printf %s\\n    1 2 3 4 match  \
                match match 8  \
                9 10 11 12 13  \
                14 match match \
                17 18 19 20 21 |
sed -net -e'/match/{h;n;//h;//!H;G;s/\n/&/5;D;}' -ep

... 5 를 제거하려는 줄 수 (일치하는 줄 포함) 로 바꿉니다.


1
2
3
4
12
13
14
21
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.