다음 유용한 find 명령은 이름 태그의 값을 인쇄합니다.
find /tmp -type f -name '*.xml' -exec grep -o -P '(?<=<Name>).*(?=</Name>)' {} \;
문제는 /tmp 아래에 여러 개의 xml 파일이 있는 경우 어떤 xml 파일에 이름 태그가 있는지 알 수 없다는 것입니다.
즉, 이 find 구문은 Name 값을 인쇄합니다.
하지만 xml 파일 이름은 없습니다.
grep이 일치할 때 파일 이름을 인쇄하는 방법을 제안하십시오.
(?<=<Name>).*(?=</Name>)
답변1
적절한 XML 파서(여기서 사용하는 것)를 사용하여 파일 이름 접미사가 at 이하인 모든 XML 파일에서 xmlstarlet
모든 노드의 값을 추출하려면 다음을 수행합니다.Name
.xml
/tmp
find /tmp -type f -name '*.xml' -exec xmlstarlet sel -t -v '//Name' -nl {} +
이것은 실제로아니요<Name>
여는 태그와 해당하는 닫는 태그가 같은 줄에 있어야 하며 </Name>
, 명령처럼 노드에 Name
속성이 없어도 됩니다 grep
.
xmlstarlet
현재 처리 중인 파일 이름과 같은 추가 정보 출력을 사용하고 파일에 실제로 노드가 있는 경우에만 이 작업을 수행하려면 Name
위 명령 xmlstarlet
의 호출을 다음으로 바꾸세요 .find
xmlstarlet sel -t -i '//Name' -o '### ' -f -o ':' -nl -v '//Name' -nl
그러면 파일에 노드가 포함된 경우에만 접두사 ###
와 접미사가 붙은 XML 파일의 경로 이름이 출력됩니다 . 그 다음에는 문서의 각 노드 값이 나옵니다 .:
Name
Name
사용 grep
:
grep
명령줄에 여러 파일이 제공되면 일치 항목이 포함된 파일의 파일 이름이 항상 출력됩니다. 파일이 하나만 전달되면 파일 이름이 인쇄되지 않습니다.
실제 일치 항목과 함께 파일 이름이 항상 인쇄되도록 하려면 /dev/null
다음을 grep에 추가 파일로 추가하세요.
find /tmp -type f -name '*.xml' -exec grep -o -P '(?<=<Name>).*(?=</Name>)' {} /dev/null \;
또는 통화 수를 잠재적으로 줄이려면 다음을 대신 grep
사용하세요 find -exec grep ... {} +
.
find /tmp -type f -name '*.xml' -exec grep -o -P '(?<=<Name>).*(?=</Name>)' /dev/null {} +
최소한 GNU, OpenBSD 및 FreeBSD는 파일이 하나만 제공되더라도 항상 파일 이름을 인쇄하는 플래그를 지원 grep
합니다 . 당신이 그것을 사용하고 있기 때문에 아마도 GNU를 사용하고 있을 것입니다 .grep
-H
grep -P
grep
답변2
grep에 "-H" 매개변수만 지정하면 grep이 처리할 파일이 하나만 있는 경우에도(귀하의 경우처럼) 파일 이름이 항상 인쇄됩니다.
답변3
이는 grep
xml/html 파일(문서)을 구문 분석하는 데 적합한 도구가 아니며 강력하고 안정적인 솔루션을 제공하지 않습니다. "올바른" xml/html 파서를 사용하세요.xmlstarlet
:
find /tmp -type f -name '*.xml' -exec xmlstarlet sel -t -m "//Name" -f -n {} \;
xmlstarlet sel -t -m "//Name" -f -n
-f
-입력 파일 이름은 입력 xml 문서가 ( ) XPATH 표현식과 일치하는 경우에만 인쇄됩니다-m
(옵션으로 확인)."//Name"
답변4
찾은 줄 다음에 파일 이름을 인쇄해도 괜찮다면 언제든지 "-print" 옵션을 찾을 수 있습니다:
find /tmp -type f -name '*.xml' -exec grep -o -P '(?<=<Name>).*(?=</Name>)' {} \; -print