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

나는 이것을 사용한다

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

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

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

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

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



답변

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

sed '/bar/,+1 d'

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


답변

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

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

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

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

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

답변

나는 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 / 줄을 건너 뛰기 위해 계속 읽습니다.


답변

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

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

샘플 데이터 :

$ cat sample1.txt
foo
bar
biz
baz
buz

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


답변

일치하는 줄 바로 뒤에있는 줄을 제거해야하는 경우 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