일치하는 문자열에서 N번째 줄 제거(여러 번 발생하지만 첫 번째 발생만 제거)

일치하는 문자열에서 N번째 줄 제거(여러 번 발생하지만 첫 번째 발생만 제거)
CPUNAME AGENT_1
  DESCRIPTION "MANAGER CPU"
  OS UNIX
  NODE xxxxxxxxx.xxx.xxx.cxx TCPADDR 31111
  DOMAIN MASTERDM
  FOR MAESTRO
    TYPE MANAGER
    IGNORE
    AUTOLINK ON
    BEHINDFIREWALL OFF
    FULLSTATUS ON
END


CPUNAME AGENT_2
  DESCRIPTION "MANAGER CPU"
  OS UNIX
  NODE xxxxxxxxx.xxx.xxx.cxx TCPADDR 31111
  TIMEZONE abc
  DOMAIN MASTERDM
  FOR MAESTRO
    TYPE MANAGER
    IGNORE
    AUTOLINK ON
    BEHINDFIREWALL OFF
    FULLSTATUS ON
END


CPUNAME AGENT_3
  DESCRIPTION "MANAGER CPU"
  OS UNIX
  NODE xxxxxxxxx.xxx.xxx.cxx TCPADDR 31111
    TYPE MANAGER
    IGNORE
    AUTOLINK ON
    BEHINDFIREWALL OFF
    FULLSTATUS ON
END


DOMAIN MASTERDM
  *MANAGER AGENT_1
  ISMASTER
END
  1. 위 파일에서 먼저 패턴 일치 "TYPE" 뒤에 "IGNORE" 줄을 추가했습니다.

    sed -i '/^    TYPE.*/a IGNORE' filename 
    
  2. 특정 CPU(예: AGENT_1 AGENT_3)에 대한 IGNORE 플래그를 제거해야 하지만 IGNORE 위치가 위에 표시된 대로 고정되어 있지 않습니다. 다른 블록의 숫자 8, 9, 6이 곧 출시될 예정입니다. 지금은 IGNORE 플래그가 위치 8에 있는 파일을 편집하고 있는 CPU를 알고 있으므로 루프를 사용하여 forIGNORE를 제거합니다.

    for s in `cat $INPUT_FILE | awk '{print $1}'`; do
            echo $s
            sed -i "/$s/!b;n;n;n;n;n;n;n;d" Filename
    done
    
  3. 내가 아는 한, NODE 위치는 모든 블록에 대해 항상 고정되어 있으므로 다음 명령을 사용하여 라인을 교체했습니다.

    for n in `cat $INPUT_FILE`; do
        CPU=$(echo $n | cut -f1)
        NODE=$(echo $n | cut -f2)
        echo "$CPU"
        echo "$NODE"
        sed -i "/$CPU/!b;n;n;n;c $NODE" filename
    done
    

위의 모든 내용은 특정 CPU에 대한 무시를 제거하는 것을 제외하고는 잘 작동합니다(고정 라인이 아닌 경우). 솔루션 개선을 위한 소중한 제안을 보내주세요.

답변1

작업: IGNORECPU 이름을 지정하는 줄 삭제

줄 을 제거하려면 IGNORE다음을 사용할 수 있습니다.AGENT_1AGENT_3

awk '$1 == "CPUNAME" && ($2 == "AGENT_1" || $2 == "AGENT_3") { x=1 }
/^END$/ { x=0 }
x && /^ *IGNORE$/ { next }
1' inputfile

필요에 따라 기준에서 CPU 이름을 추가하거나 제거할 수 있습니다.

그러면 수정된 데이터가 표준 출력으로 인쇄됩니다. 일반적으로 말해서, 문제가 발생하면 데이터가 손실될 수 있으므로 내부 편집을 권장하지 않습니다. 입력 파일을 내부 편집을 지원하지 않는 도구로 바꾸고 싶다면 언제든지 다음과 같은 것을 사용할 수 있습니다.

awk 'some script' inputfile > tempfile && mv tempfile inputfile

설명하다

  • $1 == "CPUNAME" && ($2 == "AGENT_1" || $2 == "AGENT_3")첫 번째 필드가 CPUNAME지정된 이름 중 하나이고 두 번째 필드가 지정된 이름 중 하나이면 조건이 일치합니다.
  • { x=1 }이 블록에서 제거하려는 항목을 x표시하는 플래그를 설정합니다.IGNORE
  • /^END$/ { x=0 }전체 라인이 블록 끝에 있는 클리어 플래그와 일치하는 경우 END.x
  • x && /^ *IGNORE$/플래그가 설정된 경우에만 IGNORE선행 공백이 있는 줄을 일치시키는 조건입니다 .x
  • { next }라인의 추가 처리를 건너뜁니다. 즉, 인쇄하지 않습니다.
  • 1true기본 작업이 없는 (= 행당) 조건 입니다 print. (예를 들어 와 같이 더 자세히 작성할 수 있습니다 { print }.)

질문의 예시 입력을 사용하세요.

CPUNAME AGENT_1
  DESCRIPTION "MANAGER CPU"
  OS UNIX
  NODE xxxxxxxxx.xxx.xxx.cxx TCPADDR 31111
  DOMAIN MASTERDM
  FOR MAESTRO
    TYPE MANAGER
    IGNORE
    AUTOLINK ON
    BEHINDFIREWALL OFF
    FULLSTATUS ON
END


CPUNAME AGENT_2
  DESCRIPTION "MANAGER CPU"
  OS UNIX
  NODE xxxxxxxxx.xxx.xxx.cxx TCPADDR 31111
  TIMEZONE abc
  DOMAIN MASTERDM
  FOR MAESTRO
    TYPE MANAGER
    IGNORE
    AUTOLINK ON
    BEHINDFIREWALL OFF
    FULLSTATUS ON
END


CPUNAME AGENT_3
  DESCRIPTION "MANAGER CPU"
  OS UNIX
  NODE xxxxxxxxx.xxx.xxx.cxx TCPADDR 31111
    TYPE MANAGER
    IGNORE
    AUTOLINK ON
    BEHINDFIREWALL OFF
    FULLSTATUS ON
END


DOMAIN MASTERDM
  *MANAGER AGENT_1
  ISMASTER
END

출력은 다음과 같습니다

CPUNAME AGENT_1
  DESCRIPTION "MANAGER CPU"
  OS UNIX
  NODE xxxxxxxxx.xxx.xxx.cxx TCPADDR 31111
  DOMAIN MASTERDM
  FOR MAESTRO
    TYPE MANAGER
    AUTOLINK ON
    BEHINDFIREWALL OFF
    FULLSTATUS ON
END


CPUNAME AGENT_2
  DESCRIPTION "MANAGER CPU"
  OS UNIX
  NODE xxxxxxxxx.xxx.xxx.cxx TCPADDR 31111
  TIMEZONE abc
  DOMAIN MASTERDM
  FOR MAESTRO
    TYPE MANAGER
    IGNORE
    AUTOLINK ON
    BEHINDFIREWALL OFF
    FULLSTATUS ON
END


CPUNAME AGENT_3
  DESCRIPTION "MANAGER CPU"
  OS UNIX
  NODE xxxxxxxxx.xxx.xxx.cxx TCPADDR 31111
    TYPE MANAGER
    AUTOLINK ON
    BEHINDFIREWALL OFF
    FULLSTATUS ON
END


DOMAIN MASTERDM
  *MANAGER AGENT_1
  ISMASTER
END


반대 작업: IGNORE행 삽입

실제 입력 파일에 IGNORE줄이 없으면 지정된 CPU 이름과 일치하는(또는 일치하지 않는) 줄 뒤의 블록에만 줄을 삽입하는 스크립트를 사용할 수도 있습니다 TYPE.

예: IGNORE둘 중 하나도 일치하지 않는 블록을 삽입하고AGENT_1AGENT_3

awk '$1 == "CPUNAME" && ($2 != "AGENT_1" && $2 != "AGENT_3") { x=1 }
/^END$/ { x=0 }
1
x && $1 == "TYPE" { print "    IGNORE" }' inputfile

설명하다:(첫 번째 스크립트와만 다름)

  • $1 == "CPUNAME" && ($2 != "AGENT_1" && $2 != "AGENT_3")첫 번째 필드 CPUNAME와 두 번째 필드에는 이름이 없습니다.
  • x && $1 == "TYPE"플래그가 x설정되고 첫 번째 필드는TYPE
  • { print " IGNORE" }라인 인쇄 IGNORE( TYPE라인 뒤)

AGENT_1CPU를 사용한 입력 예.. AGENT_4및 줄 없음 IGNORE:

CPUNAME AGENT_1
  DESCRIPTION "MANAGER CPU"
  OS UNIX
  NODE xxxxxxxxx.xxx.xxx.cxx TCPADDR 31111
  DOMAIN MASTERDM
  FOR MAESTRO
    TYPE MANAGER
    AUTOLINK ON
    BEHINDFIREWALL OFF
    FULLSTATUS ON
END


CPUNAME AGENT_2
  DESCRIPTION "MANAGER CPU"
  OS UNIX
  NODE xxxxxxxxx.xxx.xxx.cxx TCPADDR 31111
  TIMEZONE abc
  DOMAIN MASTERDM
  FOR MAESTRO
    TYPE MANAGER
    AUTOLINK ON
    BEHINDFIREWALL OFF
    FULLSTATUS ON
END


CPUNAME AGENT_3
  DESCRIPTION "MANAGER CPU"
  OS UNIX
  NODE xxxxxxxxx.xxx.xxx.cxx TCPADDR 31111
    TYPE MANAGER
    AUTOLINK ON
    BEHINDFIREWALL OFF
    FULLSTATUS ON
END


CPUNAME AGENT_4
  DESCRIPTION "MANAGER CPU"
  OS UNIX
  NODE xxxxxxxxx.xxx.xxx.cxx TCPADDR 31111
    TYPE MANAGER
    AUTOLINK ON
    BEHINDFIREWALL OFF
    FULLSTATUS ON
END


DOMAIN MASTERDM
  *MANAGER AGENT_1
  ISMASTER
END

결과 출력:

CPUNAME AGENT_1
  DESCRIPTION "MANAGER CPU"
  OS UNIX
  NODE xxxxxxxxx.xxx.xxx.cxx TCPADDR 31111
  DOMAIN MASTERDM
  FOR MAESTRO
    TYPE MANAGER
    AUTOLINK ON
    BEHINDFIREWALL OFF
    FULLSTATUS ON
END


CPUNAME AGENT_2
  DESCRIPTION "MANAGER CPU"
  OS UNIX
  NODE xxxxxxxxx.xxx.xxx.cxx TCPADDR 31111
  TIMEZONE abc
  DOMAIN MASTERDM
  FOR MAESTRO
    TYPE MANAGER
    IGNORE
    AUTOLINK ON
    BEHINDFIREWALL OFF
    FULLSTATUS ON
END


CPUNAME AGENT_3
  DESCRIPTION "MANAGER CPU"
  OS UNIX
  NODE xxxxxxxxx.xxx.xxx.cxx TCPADDR 31111
    TYPE MANAGER
    AUTOLINK ON
    BEHINDFIREWALL OFF
    FULLSTATUS ON
END


CPUNAME AGENT_4
  DESCRIPTION "MANAGER CPU"
  OS UNIX
  NODE xxxxxxxxx.xxx.xxx.cxx TCPADDR 31111
    TYPE MANAGER
    IGNORE
    AUTOLINK ON
    BEHINDFIREWALL OFF
    FULLSTATUS ON
END


DOMAIN MASTERDM
  *MANAGER AGENT_1
  ISMASTER
END

답변2

사용행복하다(이전 Perl_6)

~$ raku -e 'my @a = slurp.split("\n\n"); .subst("    IGNORE\n").put if .match(/AGENT_1 | AGENT_3/) for @a;'  file

즉, 위의 코드는 Raku 프로그래밍 언어를 사용합니다. Use는 전체 파일을 읽고 slurp이를 \n\n연속 개행 문자로 레코드로 분할하여 배열에 저장합니다 @a. 그런 다음 레코드가 match필수 레코드 중 하나 인 경우 " " 행이 아무것도 대체되지 않은 상태 로 AGENT레코드가 삭제됩니다 (예: 삭제됨).putIGNORE\n

https://raku.org

관련 정보