sed 또는 awk : 패턴에 따라 n 줄 삭제


105

sed (또는 유사한 도구-예를 들어 awk)에서 패턴과 숫자 범위를 어떻게 혼합합니까? 내가 원하는 것은 파일의 특정 줄을 일치시키고 계속하기 전에 다음 n 줄을 삭제하는 것입니다. 파이프 라인의 일부로 수행하고 싶습니다.

답변:


186

나는 이것에 갈 것이다.

패턴 뒤의 5 줄 삭제 (패턴이있는 줄 포함) :

sed -e '/pattern/,+5d' file.txt

패턴 뒤의 5 줄 삭제 (패턴이있는 줄 제외) :

sed -e '/pattern/{n;N;N;N;N;d}' file.txt

14
점을 유의 +N패턴이 GNU 확장이다. 두 번째 예제에서 첫 번째 n를로 변경하여 N패턴이있는 선을 포함하도록합니다.
추후 공지가있을 때까지 일시 중지되었습니다.

2
패턴이 일치 한 후 모든 줄을 삭제하는 방법은 무엇입니까? sed -e '/ <!-# content end-> </ div> /, $ d'out.txt를 사용하고 있지만 다음과 같은 오류가 발생합니다. sed : -e expression # 1, char 24 : extra characters after 명령 미리 감사드립니다.
N mol

8
일어나는 일은 비슷하지만 각 경우에 약간 씩 다릅니다. 첫 번째 레시피에서 /pattern/,+5범위를 정의합니다. 범위는 "패턴"( /pattern/)을 포함하는 줄로 시작하고 5 줄 뒤에 끝납니다 ( +5). 마지막 문자 d는 해당 범위의 각 행에서 실행할 명령으로 "삭제"입니다. 두 번째 레시피에서는 범위를 일치시키는 대신 패턴 ( /pattern/)을 포함하는 줄에서 일치 한 다음 일련의 명령을 실행합니다. {n;N;N;N;N;d}, 기본적으로 다음 줄 ( n)을 인쇄 한 다음 다음 4 줄을 읽고 마지막으로 삭제합니다 ( N;N;N;N;d).
pimlottc 2013 년

18
Mac / OS X 시스템에서는 닫는 대괄호 앞에 세미콜론을 추가해야합니다.sed -e '/pattern/{n;N;N;N;N;d;}' file.txt
AvL

1
완전성을 위해 : 특정 패턴을 따르는 모든 행삭제 하려면 다음을something 수행하십시오. sed -E '/^something$/,$d', 여기서는 -EPOSIX 이식성 확장 정규식입니다.
not2qubit

7

GNU 확장이없는 경우 (예 : macOS) :

패턴 뒤 5 줄 삭제 (패턴이있는 줄 포함)

 sed -e '/pattern/{N;N;N;N;d;}'

내부 -i ''편집을 위해 추가 합니다.


6

간단한 awk솔루션 :

일치하는 줄을 찾는 데 사용할 정규식이 쉘 변수에 저장되고 $regex건너 뛸 줄 수라고 가정합니다 $count.

일치하는 줄 건너 뛰어야 하는 경우 ( $count + 1줄 건너 뛰기) :

... | awk -v regex="$regex" -v count="$count" \
  '$0 ~ regex { skip=count; next } --skip >= 0 { next } 1'

는 IF 일치하는 라인은해야 하지 건너 뛸 수 ( $count 경기는 건너 뜁니다) :

... | awk -v regex="$regex" -v count="$count" \
  '$0 ~ regex { skip=count; print; next } --skip >= 0 { next } 1'

설명:

  • -v regex="$regex" -v count="$count"같은 이름의 변수를 awk기반으로 변수를 정의 합니다 .
  • $0 ~ regex 관심 라인과 일치
    • { skip=count; next }건너 뛰기 횟수를 초기화하고 다음 줄로 진행하여 효과적으로 일치하는 줄을 건너 뜁니다. 두 번째 솔루션에서는 print이전 next이 건너 뛰지 않도록 합니다.
    • --skip >= 0 건너 뛰기 횟수를 줄이고 (여전히)> = 0 인 경우 조치를 취합니다. 이는 당면한 줄을 건너 뛰어야 함을 의미합니다.
    • { next } 다음 줄로 진행하여 효과적으로 현재 줄을 건너 뜁니다.
  • 1일반적으로 사용되는 속기입니다 { print }. 즉, 현재 행이 단순히 인쇄됩니다.
    • 일치하지 않고 건너 뛰지 않은 줄만이 명령에 도달합니다.
    • 그 이유 1에 해당되고 { print }그는 인 1정의로 항상 (블록) 연관된 동작이 무조건 실행되도록하는 수단은, 참으로 평가하는 부울 패턴으로 해석된다. 이 경우 연관된 조치 가 없으므로awk 기본적으로 행 을 인쇄 합니다.

3

이것은 당신을 위해 일할 수 있습니다.

cat <<! >pattern_number.txt
> 5 3
> 10 1
> 15 5
> !
sed 's|\(\S*\) \(\S*\)|/\1/,+\2{//!d}|' pattern_number.txt |
sed -f - <(seq 21)
1 
2
3
4
5
9
10
12
13
14
15
21

10
와우, 그것은 비밀 스럽습니다.
pimlottc 2013 년

3
영리한 (GNU-Sed 전용) 솔루션이지만 설명을 추가하지 않으면 혜택을받는 사람은 거의 없습니다. pattern_number.txt첫 번째 열에서 일치시킬 패턴을 포함하고 두 번째 열에서 건너 뛸 행 수를 포함하는 2 열 파일입니다. 첫 번째 sed명령은 파일을 sed해당 일치 및 건너 뛰기를 수행 하는 스크립트 로 변환합니다 . 해당 스크립트는 -f및 stdin ( -)을 통해 두 번째 sed명령에 제공됩니다. 두 번째 sed명령은의 출력에서 ​​형성된 샘플 임시 입력 파일에서 seq 21작동하여 작동하는지 보여줍니다.
mklement0

또한 솔루션에는 한 가지주의 사항이 있습니다. 첫 번째 줄 (패턴과 일치하는 줄)을 건너 뛰지 않는 데 사용하는 방법 은 범위에서 중복 된 줄을 건너 뛰지 않는 부작용도 있습니다.
mklement0

그것은 sed의 인상적인 사용입니다.
트래비스로드 먼

3

Perl 사용

$ cat delete_5lines.txt
1
2
3
4
5 hello
6
7
8
9
10
11 hai
$ perl -ne ' BEGIN{$y=1} $y=$.  if /hello/ ; print if $y==1 or $.-$y > 5 ' delete_5lines.txt
1
2
3
4
11 hai
$

2

이 솔루션을 사용하면 "n"을 매개 변수로 전달할 수 있으며 파일에서 패턴을 읽습니다.

awk -v n=5 '
    NR == FNR {pattern[$0]; next}
    {
        for (patt in pattern) {
            if ($0 ~ patt) {
                print # remove if you want to exclude a matched line
                for (i=0; i<n; i++) getline
                next
            }
        }
        print
    }
' file.with.patterns -

"-"라는 파일은 awk의 stdin을 의미하므로 파이프 라인에 적합합니다.


2
awk는 내가 생각한 것보다 훨씬 더 펄과 비슷할 수 있습니다!
Martin DeMello 2010
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.