다음과 같이 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}'
xml2
XML 형식의 데이터를 줄 기반 텍스트 유틸리티(예: awk
, 또는 sed
, 또는 등)를 사용하여 처리하기에 적합한 줄 perl
기반 형식 으로 변환합니다. 2xml
라인 기반 형식을 다시 올바른 형식의 XML로 변환하는 해당 프로그램이 함께 제공됩니다 .
더 복잡한 작업에는 사용할 것입니다.xmlstarlet
xmlstarlet
XML 파일의 데이터를 나열, 쿼리, 추출 및 수정하는 데 사용할 수 있는 XML 처리 도구입니다.
둘 다 데비안 및 기타 Linux 배포판용으로 패키지될 수 있습니다.
내 생각에 가장 좋은 해결책은 유사 perl
하거나 python
XML 구문 분석 라이브러리가 있는 언어를 사용하는 것입니다. 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"