하위 xml 태그를 조건부로 제거하는 쉘 스크립트

하위 xml 태그를 조건부로 제거하는 쉘 스크립트

다음 내용이 포함된 xml 파일이 있습니다.

<contracts>
    <clients>
        <client>
            <name>Nicol</name>
            <clientRef>123</clientRef>
        </client>
        <client>
            <name>Basil</name>
            <clientRef>8234</clientRef>
        </client>
    </clients>
    <entries>
        <entry>
            <regCode>BCG</regCode>
            <clientRef>63352</clientRef>
        </entry>
        <entry>
            <regCode>TYD</regCode>
            <clientRef>3242</clientRef>
        </entry>
    </entries>
</contracts>  

xml 태그 "clientRef"는 클라이언트 및 항목 섹션에 있습니다. 하지만 클라이언트 섹션에서 clientRef 태그만 제거하면 됩니다.

원하는 출력은 다음과 같습니다.

<contracts>
    <clients>
        <client>
            <name>Nicol</name>
        </client>
        <client>
            <name>Basil</name>
        </client>
    </clients>
    <entries>
        <entry>
            <regCode>BCG</regCode>
            <clientRef>63352</clientRef>
        </entry>
        <entry>
            <regCode>TYD</regCode>
            <clientRef>3242</clientRef>
        </entry>
    </entries>
</contracts>

저는 shell 및 sed 명령을 처음 사용합니다. 쉘 스크립트를 사용하여 clientRef 태그를 제거하는 방법은 무엇입니까?

답변1

가능하지만 이는아주 아주 나쁜 생각이야sed정규식 기반 도구를 사용하여 XML 또는 HTML을 구문 분석해 보세요 . 이는 간단한 경우에는 작동할 수 있지만 제대로 하기는 어렵습니다.전문가에게도, 약간 더 복잡한 상황의 경우. 따라서 다음과 같은 XML 파서를 사용하십시오 xmlstarlet(운영 체제 저장소에서 설치 가능해야 함).

$ xmlstarlet ed -d '//client/clientRef' file.xml  
<?xml version="1.0"?>
<contracts>
  <clients>
    <client>
      <name>Nicol</name>
    </client>
    <client>
      <name>Basil</name>
    </client>
  </clients>
  <entries>
    <entry>
      <regCode>BCG</regCode>
      <clientRef>63352</clientRef>
    </entry>
    <entry>
      <regCode>TYD</regCode>
      <clientRef>3242</clientRef>
    </entry>
  </entries>
</contracts>

이는 ed"이 파일을 편집한다"는 의미이며, 이는 아래의 항목을 -d '//client/clientRef'"삭제"한다는 의미입니다 .clientRefclient


이 특별한 경우에는 간단한 텍스트 구문 분석 도구를 사용할 수도 있으므로 예를 제공하겠습니다. 하지만 더 복잡한 작업에서는 이 작업을 수행하지 말고 작은 변경으로도 중단될 수 있다는 점에 유의하세요. 입력 데이터:

$ awk '{ 
        if(/<clients>/){a=1}
        else if(/<\/clients>/){a=0} 
        if(/<clientRef>/ && a){ next}
       }1;' file.xml 
<contracts>
    <clients>
        <client>
            <name>Nicol</name>
        </client>
        <client>
            <name>Basil</name>
        </client>
    </clients>
    <entries>
        <entry>
            <regCode>BCG</regCode>
            <clientRef>63352</clientRef>
        </entry>
        <entry>
            <regCode>TYD</regCode>
            <clientRef>3242</clientRef>
        </entry>
    </entries>
</contracts>  

답변2

xqXML 파서 사용 (섹션yq), 이는 래퍼입니다 jq(따라서 XML/JSON 트랜스코딩을 수행함).

$ xq -x 'del(.contracts.clients.client[].clientRef)' file.xml
<contracts>
  <clients>
    <client>
      <name>Nicol</name>
    </client>
    <client>
      <name>Basil</name>
    </client>
  </clients>
  <entries>
    <entry>
      <regCode>BCG</regCode>
      <clientRef>63352</clientRef>
    </entry>
    <entry>
      <regCode>TYD</regCode>
      <clientRef>3242</clientRef>
    </entry>
  </entries>
</contracts>

관련 정보