일치하는 행 뒤의 X 행과 그 앞의 Y 행을 삭제합니다.

일치하는 행 뒤의 X 행과 그 앞의 Y 행을 삭제합니다.

다음 문자열이 있습니다.

core1@pci0:2:0:1:  class=0x020000 rev=0x00 hdr=0x00 vendor=0x1453
    vendor     = 'MicSystem'
    device     = 'controller'
    class      = network
    subclass   = ethernet
none65@pci0:2:0:2:      class=0x080100 rev=0x00 hdr=0x00 vendor=0x1453
    vendor     = 'MicSystem'
    device     = 'interface'
    class      = base peripheral
    subclass   = DMA controller
core1@pci0:2:0:1:  class=0x020000 rev=0x00 hdr=0x00 vendor=0x1453
    vendor     = 'MicSystem'
    device     = 'controller'
    class      = network
    subclass   = ethernet

"class = Base Peripheral" 앞에 3줄, 그 뒤에 1줄을 삭제해야 합니다. 예를 들면 다음과 같습니다.

core1@pci0:2:0:1:  class=0x020000 rev=0x00 hdr=0x00 vendor=0x1453
    vendor     = 'MicSystem'
    device     = 'controller'
    class      = network
    subclass   = ethernet
core1@pci0:2:0:1:  class=0x020000 rev=0x00 hdr=0x00 vendor=0x1453 
    vendor     = 'MicSystem'
    device     = 'controller'
    class      = network
    subclass   = ethernet

나는 이것을 할 수 없었습니다. 이것은 FreeBSD 운영 체제에서 수행되었습니다.

답변1

실제 사용에드또는전임자:

ed -s file <<EOF
g/base peripheral/-3;+4d
%p
EOF
printf '%s\n' 'g/base peripheral/-3;+4d' '%p' | ex -s file

lobal은 g모든 행을 "기본 경계"로 표시하고 d지정된 범위를 삭제합니다. 그런 다음 %p파일을 인쇄하십시오. w를 사용하여 파일의 변경 사항을 저장할 수 있습니다 .

답변2

이 시도 awk:

awk '
FNR==NR && /class[[:blank:]]*=[[:blank:]]*base peripheral/{x=NR; nextfile;}
FNR!=NR && (FNR < x-3 || FNR > x+1)
' file file

file두 번 먹이세요 awk. 처음에는 해당 행을 찾습니다(여러 개가 있는 경우 첫 번째 행만 일치합니다!). 두 번째로 생략할 줄을 제외한 줄을 인쇄합니다.

명령 출력과 함께 사용하려면 다음을 사용하십시오.

awk '...' <(command) <(command)

또는

output="$(command)"
awk '...' <(printf '%s' "$output") <(printf '%s' "$output")

답변3

가장 간단한 방법은 아마도 다음과 같을 것입니다. 모든 Unix 시스템의 모든 쉘에서 awk를 사용하는 것입니다:

$ cat tst.awk
$0 ~ re {
    for (i=(NR-b); i<=(NR+a); i++) {
        skip[i]
    }
}
{ lines[NR] = $0 }
END {
    for (i=1; i<=NR; i++) {
        if ( !(i in skip) ) {
            print lines[i]
        }
    }
}

$ awk -v b=3 -v a=1 -v re='class[[:space:]]*=[[:space:]]*base peripheral' -f tst.awk file
    core1@pci0:2:0:1:  class=0x020000 rev=0x00 hdr=0x00 vendor=0x1453 device=0xa2d2 subvendor=0x1453 subdevice=0x0008
        vendor     = 'MicSystem'
        device     = 'controller'
        class      = network
        subclass   = ethernet
    core1@pci0:2:0:1:  class=0x020000 rev=0x00 hdr=0x00 vendor=0x1453 device=0xa2d2 subvendor=0x1453 subdevice=0x0008
            vendor     = 'MicSystem'
            device     = 'controller'
            class      = network
            subclass   = ethernet

입력이 셸에 저장되지 않고 파이프에서 나오는 경우 whatever | awk -v ... -f tst.awk입력을 스크립트에 전달하는 모든 작업을 실행하거나 수행하십시오.

위의 솔루션과 마찬가지로 ed전체 입력이 메모리로 읽혀지지만 입력 길이가 수억 줄이 아닌 경우에는 문제가 되지 않습니다. 이것이 실제로 그렇다면 b현재 행이 정규식과 일치하지 않을 때 항상 배열의 첫 번째 요소를 인쇄하도록 크기 배열인 스크롤 버퍼를 구현할 수 있습니다. 그러나 이 경우 작성하는 데 더 많은 생각이 필요하고 작성하기가 더 어렵습니다. 겹치는 범위를 처리합니다.

답변4

문제는 이 행 앞뒤에 너무 많은 행을 삭제하는 것으로 설명되지만 이러한 의도된 편집의 효과는 "속성이 class해당 값을 갖는 항목 삭제 base peripheral"라는 더 높은 수준의 의미를 갖는다는 것이 분명합니다.

더 큰 문서의 구조와 관련된 이러한 유형의 변환 작업에 매우 적합한 언어가 있습니다.TxR.

다른 사람이 이해하기 쉬운 코드를 사용하여 필드 추출을 자세히 수행하거나 17개월 후에 귀하가 이해할 수 있도록 할 수 있습니다.

@(repeat)
@addr: class=0x@cl rev=0x@rev hdr=0x@hdr vendor=0x@ven
    vendor     = '@vendor'
    device     = '@device'
    class      = @class
    subclass   = @subclass
@  (require (nequal class "base peripheral"))
@  (output)
@addr: class=0x@cl rev=0x@rev hdr=0x@hdr vendor=0x@ven
    vendor     = '@vendor'
    device     = '@device'
    class      = @class
    subclass   = @subclass
@  (end)
@(end)

달리기:

$ txr data.txr data
core1@pci0:2:0:1: class=0x020000 rev=0x00 hdr=0x00 vendor=0x1453
    vendor     = 'MicSystem'
    device     = 'controller'
    class      = network
    subclass   = ethernet
core1@pci0:2:0:1: class=0x020000 rev=0x00 hdr=0x00 vendor=0x1453
    vendor     = 'MicSystem'
    device     = 'controller'
    class      = network
    subclass   = ethernet

여기서 패턴 일치 어설션은 @(require expr)false인 경우 불필요한 항목을 제거합니다 expr.

필터링을 임의로 복잡하게 만들고 필요에 따라 출력 형태를 쉽게 변경할 수 있습니다. 내장된 TXR Lisp 언어에는 마법 같은 초능력도 있습니다.

관련 정보