모두 제거노드 != 태그 값

모두 제거노드 != 태그 값

여기서는 XML 파서가 이상적인 방법이라는 것을 알고 있지만 내 환경에는 어떤 것도 사용 가능하거나 추가할 수 없습니다.

다음 구조를 따르는 XML을 살펴보겠습니다.

<CONTAINER>
  <FOLDER NAME="I_RS_INT">
  </FOLDER>
  <FOLDER NAME="I_R_INR">
  </FOLDER>
  <FOLDER NAME="I_RS_TRN">
  </FOLDER>
</CONTAINER>

<FOLDER NAME=Bash 스크립트에서 일치하는 모든 노드를 삭제 하거나 *RS*다음의 모든 노드를 삭제하고 싶습니다.<FOLDER NAME != $var_folder

어떤 도움이라도 대단히 감사하겠습니다!

답변1

이렇게 하면 트릭을 수행할 수 있습니다.

cat /tmp/xml  | sed -e '/<FOLDER NAME=.*RS.*>/ { N; d; }'

두 문자 사이의 패턴과 일치하는 각 줄에 대해 /{} 내의 코드가 실행됩니다. N은 또한 다음 줄을 패턴 공간에 넣은 다음 d는 다음 줄을 계속하기 전에 전체 내용을 삭제합니다. 이는 모든 POSIX 호환에서 작동합니다 sed.

<FOLDER NAME=.*RS.*>와 사이의 모든 줄을 제거하려면 다음을 시도하십시오 </FOLDER.>.

 awk '/<FOLDER NAME=.*RS.*>/,/<\/FOLDER>/ {next} {print}' xmlfile

next명령은 현재 일치 항목의 처리를 중지합니다. 다음은 간단한 것입니다 print.

답변2

이를 수행하려면 XML 파서를 사용해야 합니다. 예를 들어XML 스타명령줄에서:

$ xmlstarlet ed -d '/CONTAINER/FOLDER[contains(@NAME, "RS")]' data.xml
<?xml version="1.0"?>
<CONTAINER>
  <FOLDER NAME="I_R_INR">
  </FOLDER>
</CONTAINER>

또는,

$ var="I_R_INR"
$ xmlstarlet ed -d "/CONTAINER/FOLDER[@NAME != '$var']" data.xml
<?xml version="1.0"?>
<CONTAINER>
  <FOLDER NAME="I_R_INR">
  </FOLDER>
</CONTAINER>

첫 번째 예는 부분 문자열 일치를 수행하고 두 번째 예는 정확한 일치를 수행하므로 이 두 예는 동일하지 않습니다.


xq포장지 로 jq:

$ xq -x --arg substring "RS" 'del(.CONTAINER.FOLDER[] | select(."@NAME" | contains($substring)))' file.xml
<CONTAINER>
  <FOLDER NAME="I_R_INR"></FOLDER>
</CONTAINER>
$ xq -x --arg name "I_R_INR" 'del(.CONTAINER.FOLDER[] | select(."@NAME" != $name))' file.xml
<CONTAINER>
  <FOLDER NAME="I_R_INR"></FOLDER>
</CONTAINER>

답변3

좋아, 진지하게 - 정규식을 사용하여 XML을 구문 분석하는 것은나쁜 소식. XML은 정규 언어가 아니므로 어떤 정규 표현식도 XML을 올바르게 처리할 수 없습니다. 결과적으로 당신이 쓰는 모든 것은 나쁘고 깨지기 쉬울 것입니다.

그러나 XML정규식과 유사한 이라는 것이 있습니다 xpath.

문제를 해결하기 위해 다음을 수행합니다.

#!/usr/bin/env perl
use strict;
use warnings;
use XML::Twig;
#process the file as XML
my $twig = XML::Twig -> parsefile ( 'your_file.xml' );

#iterate 'FOLDER' elements
foreach my $folder ( $twig -> get_xpath ('//FOLDER' ) ) {
   #delete any that regex match /RS/
   if ( $folder -> att('NAME') =~ m/RS/ ) { 
      $folder -> delete;
   }
}

#print the result. 
$twig -> set_pretty_print('indented_a');
$twig -> print;

답변4

sed -r '/<FOLDER NAME=.*RS.*>/{ :X N; /<\/FOLDER>/d; bX }' file
<CONTAINER>
  <FOLDER NAME="I_R_INR">
  </FOLDER>
</CONTAINER>

관련 정보