입력 파일:
<ServiceArea type="STATE" value="DC">
<DaylightSavingsUsed value="true"/>
<FemtoSipProxyAddress value="10.13.123.100"/>
<TermAuthAAAPSK value="secret1"/>
<PDSNDOParams index="1">
<batchEndIpAddress value="68.28.121.68"/>
<batchSecurityParameterIndex value="5262006"/>
<batchStartIpAddress value="68.28.121.68"/>
</PDSNDOParams>
<PDSNDOParams index="2">
<batchEndIpAddress value="68.28.113.68"/>
<batchIOSVersion value="tia-878-a"/>
<batchStartIpAddress value="68.28.113.68"/>
</PDSNDOParams>
<PDSN1XParams index="1">
<batchEndIpAddress value="68.28.121.68"/>
<batchSecretKey value="72563130317354663167345439615433"/>
<batchSecurityParameterIndex value="5262006"/>
<batchStartIpAddress value="68.28.121.68"/>
</PDSN1XParams>
<PDSN1XParams index="2">
<batchEndIpAddress value="68.28.113.68"/>
<batchIOSVersion value="tia-878-1"/>
</PDSN1XParams>
</ServiceArea>
<ServiceArea type="ZIP" value="66221">
</ServiceArea>
<ServiceArea type="FIPS" value="46081">
<DaylightSavingsUsed value="true"/>
<MTA_Number value="22"/>
<BC10_Utilization value="476,487,526"/>
</ServiceArea>
<ServiceArea type="FIPS" value="01824">
</ServiceArea>
사이에 데이터가 없는 모든 행을 삭제하고 싶습니다.
<ServiceArea type=
</ServiceArea>
위 입력에서 다음을 제거해야 합니다.
<ServiceArea type="ZIP" value="66221">
</ServiceArea>
그리고
<ServiceArea type="FIPS" value="01824">
</ServiceArea>
답변1
스크립트(스타일시트라고도 함)를 xsltproc
통해 XML 파일을 처리 할 수 있습니다 . xslt
여기에는 xslt 스크립트와 제어 bash 스크립트가 포함됩니다. 예를 들어:
dropem.xslt
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="ServiceArea">
<xsl:if test="count(*)>0">
<ServiceArea>
<xsl:copy-of select="node()"/>
</ServiceArea>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
dropem.sh
#!/bin/bash
cat <<EOF | xsltproc dropem.xslt - | tail -n +2
<ALL>
$(cat)
</ALL>
EOF
실제 명령은 다음과 같습니다.
./dropem.sh < infile > outfile
참고: xslt
스크립트에는 ServiceArea 노드와 일치하는 "템플릿" 요소가 포함되어 있으며 조건에 따라(하위 노드가 있는 경우) 이를 결과에 복사합니다.
xsltproc
단일 XML 트리만 처리되므로 입력은 닫힌 태그 쌍으로 래핑되어야 합니다 . 패키징은 데이터 파일을 트리로 만듭니다. 줄 바꿈은 출력에서 유지되지 않으며 출력은 ServiceArea 하위 트리 목록이기도 합니다.
<?xml ...
그러나 필연적인 프리앰블 및 빈 줄 방출을 방지하기 위해 출력이 잘립니다 .xsltproc
이 접근 방식의 장점은 입력 파일 행 형식에 덜 민감하다는 것입니다. 단점은 xslt
덜 일반적인 언어를 사용한다는 것입니다.
답변2
노드를 xmlstarlet
감지하려는 방법에 따라 다양한 방법으로 이 작업을 수행 할 수 있습니다 .ServiceArea
모든
ServiceArea
"텍스트 노드" 노드를 삭제합니다.xmlstarlet ed -d '//ServiceArea[text()]' file.xml
ServiceArea
자식이 없는 모든 노드를 제거합니다 .xmlstarlet ed -d '//ServiceArea[count(*)=0]' file.xml
둘 다 문서 형식이 올바른지에 따라 달라집니다. 예제 문서에는 여러 루트 노드가 포함되어 있으므로 이는 그렇지 않습니다. 이 문제를 해결하는 것은 쉽습니다. 예를 들어 문서의 <root>
시작과 끝 부분에 추가하면 됩니다.</root>
답변3
모든 사람들은 올바른 XML 구문 분석 도구를 사용하여 xml을 편집하라고 말할 것이지만 다음은 ServiceArea 태그가 별도의 줄에 있다고 가정하는 간단한 awk 스크립트입니다.
awk '/<ServiceArea /{save = $0; next}
save!="" {
if(/<\/ServiceArea>/){ save = ""; next }
print save
save = ""
}
{ print }'
이렇게 하면 해당 행이 표시될 때 시작 태그와 함께 저장됩니다. 다음 줄을 읽을 때 저장된 줄이 있지만 현재 줄이 끝 표시인 경우 두 줄을 모두 억제합니다. 그렇지 않으면 저장된 줄을 인쇄한 다음 현재 줄을 인쇄합니다.