특정 태그 이름이 포함된 xml 파일을 찾아 태그 이름 사이의 단어를 인쇄합니다.

특정 태그 이름이 포함된 xml 파일을 찾아 태그 이름 사이의 단어를 인쇄합니다.

다음과 같이 xml 파일 형식을 찾을 수 있습니다.

find /tmp/ -type f -name '*.xml'

그러나 다음을 포함하는 XML만 찾도록 구문을 어떻게 변경할 수 있습니까?

<Name>some words</Name>

다음 사이에 내용을 인쇄합니다.

<Name> ------ </Name>

예상 출력

some words      

예 - xml 파일에는 다음이 포함됩니다.

<Name>files_with_extra_data</Name>

예상 출력

files_with_extra_data

답변1

간단한 해결책은 sed를 사용하는 것입니다.

find /tmp -name '*.xml' -exec sed -n 's/<Name>\([^<]*\)<\/Name>/\1/p' {} +

정규식은 태그를 일치시키고 태그 사이의 내용을 인쇄합니다. 이스케이프 문자를 제거하면 읽기가 더 쉽습니다.

s / <Name>([^<]*)</Name> / \1 

대괄호는 "<" 이외의 모든 문자와 일치하며 \1에 매핑됩니다.

주석에서 언급했듯이 이것은 간단한 해결책이 될 것입니다. 정규식은 구조화된 텍스트의 가능한 모든 변형에 대처할 수 없습니다. 따라서 태그나 다른 태그 사이에 여러 줄이 있으면 작동하지 않으며 실제 XML 파서를 사용해야 합니다.

답변2

이와 같은 간단한 XML 작업의 경우 다음을 사용합니다.XML2그리고 cut. (또는 sed, 또는 awk, 또는 perl).

find . -iname '*.xml' -exec bash -c 'xml2 < {}' \; | grep '/Name=' |
  cut -d '=' -f2-

또는

find . -iname '*.xml' -exec bash -c 'xml2 < {}' \; | sed -n -e 's/^[^=]*\/Name=//p'

또는

find . -iname '*.xml' -exec bash -c 'xml2 < {}' \; | 
  awk -F'=' '/Name=/ {$1=""; sub(/^ /,"",$0); print }'

( sub()awk 버전의 함수 호출은 $1을 ""로 설정한 후 남겨진 선행 공백을 제거합니다. awk는 입력 줄에서 필드를 제거할 수 없습니다. 최선의 방법은 빈 문자열로 설정하고 정리하거나 split()줄을 넣는 것입니다 . 필요하지 않은 필드를 제거하고 배열을 인쇄용 문자열로 연결합니다. 해당 함수 awk가 없으므로 직접 작성해야 합니다.join()perl

또는

find . -iname '*.xml' -exec bash -c 'xml2 < {}' \; |
  perl -F= -lane 'if (m:/Name=:) { delete @F[0]; print @F}'

xml2XML 형식의 데이터를 줄 기반 텍스트 유틸리티(예: awk, 또는 sed, 또는 등)를 사용하여 처리하기에 적합한 줄 perl기반 형식 으로 변환합니다. 2xml라인 기반 형식을 다시 올바른 형식의 XML로 변환하는 해당 프로그램이 함께 제공됩니다 .

더 복잡한 작업에는 사용할 것입니다.xmlstarlet

xmlstarletXML 파일의 데이터를 나열, 쿼리, 추출 및 수정하는 데 사용할 수 있는 XML 처리 도구입니다.

둘 다 데비안 및 기타 Linux 배포판용으로 패키지될 수 있습니다.


내 생각에 가장 좋은 해결책은 유사 perl하거나 pythonXML 구문 분석 라이브러리가 있는 언어를 사용하는 것입니다. xmlstarlet셸에서 XML 파일을 처리하는 데 적합하지만 매우 복잡한 검색을 위한 명령줄을 작성하는 것은 단지 스크립트를 작성 perl하거나 작업을 수행하는 것보다 python더 많은 작업이 됩니다(읽고 디버깅하기가 더 어려워집니다) . 부분적으로는 제가 이러한 언어로 더 많은 프로그래밍을 해왔고 사용하기가 더 쉽다는 것을 알았기 때문입니다... 하지만 대부분 제 생각에는 다양한 용도로 사용할 수 있는 범용 언어에 학습 노력을 집중하는 것이 더 낫다고 생각하기 때문입니다. 매우 특정한 일에만 사용할 수 있는 도메인별 언어/도구가 아닌 작업.

답변3

그리고 pcregrep:

pcregrep -rMh --include='\.xml\z' -o1 '(?s)<name>(.*?)</name>' .

답변4

sed -n '/Name/{s/.*<Name>//;s/<\/Name.*//;p;}' "$FULL_XML_PATH"

관련 정보