예제 출력을 따라야 합니다.
<HARDWARE>
<NAME>WIN1</NAME>
<OS>Windows 7</OS>
<IP>1.2.3.4</IP>
<DOMAIN>contoso.com</DOMAIN>
</HARDWARE>
<HARDWARE>
<NAME>WIN2</NAME>
<OS>Windows 8</OS>
<IP>10.20.30.40</IP>
<DOMAIN>contoso.com</DOMAIN>
</HARDWARE>
이를 구문 분석하는 가장 좋은 방법은 다음과 같습니다.
WIN1 Windows 7 1.2.3.4 contoso.com
WIN2 Windows 8 10.20.30.40 contoso.com
awk, sed 등과 같은 표준 도구를 사용하는 솔루션을 찾고 있습니다.
답변1
XML을 약간 수정하고 모든 XML을 상위 <DATA>
태그 1 또는 선택한 다른 명명된 파일 로 래핑합니다 data.xml
.
<DATA>
<HARDWARE>
<NAME>WIN1</NAME>
<OS>Windows 7</OS>
<IP>1.2.3.4</IP>
<DOMAIN>contoso.com</DOMAIN>
</HARDWARE>
<HARDWARE>
<NAME>WIN2</NAME>
<OS>Windows 8</OS>
<IP>10.20.30.40</IP>
<DOMAIN>contoso.com</DOMAIN>
</HARDWARE>
</DATA>
xmlstarlet
+ 사용column
xmlstarlet sel -T -t -m /DATA/HARDWARE -v "concat(NAME,' ',OS,' ',IP,' ',DOMAIN)" -n data.xml | column -t
다음을 제공합니다:
WIN1 Windows 7 1.2.3.4 contoso.com
WIN2 Windows 8 10.20.30.40 contoso.com
편집하다:
댓글과 그의 댓글에서 Peter.O의 훌륭한 성과를 바탕으로다음 사항에 답해 보세요., 다음과 같이 파이프로 구분된 2개의column -ts$'|'
출력을 로 보내겠습니다 .
xmlstarlet sel --indent-tab -T -t -m /DATA/HARDWARE -v "concat(NAME,'|',OS,'|',IP,'|',DOMAIN)" -n data.xml | column -ts$'|'
이제 필드에 공백이 있더라도 잘 정렬됩니다.
WIN1 Windows 7 1.2.3.4 release 5 contoso.com
Really long OS X Windows 8 10.20.30.40 contoso.com
1. 또는 { echo '<DATA>'; cat file_name; echo '</DATA>'; } | xmlstarlet ...
아래 주석에서 Peter.O가 지적한 대로 사용하십시오.
2. 공백을 구분 기호로 사용하면 열이 올바르게 정렬되지 않습니다.
답변2
귀하의 예제와 GNU sed를 사용하여:
sed -n 's/<[^>]*>//g;s/^ *//g;/./p' file | paste -d ";" - - - - | column -t -s ";"
산출:
WIN1 윈도우 7 1.2.3.4 contoso.com WIN2 윈도우 8 10.20.30.40 contoso.com
귀하의 파일에 해당 내용이 없다고 가정합니다 ;
. CSV를 원하면 삭제하세요 | column -t -s ";"
.
답변3
다음 awk
스크립트(및 column
출력 목록)는 모든 배치 순서를 처리합니다.아들- 태그 및 태그를 구분하는 공백 - 즉. OP의 예제 입력 형식과 다음 예제를 처리합니다.공백 없음그리고다른 순서하위 태그:
<HARDWARE><OS>Windows 7</OS><IP>1.2.3.4</IP><DOMAIN>contoso.com</DOMAIN><NAME>WIN1</NAME></HARDWARE><HARDWARE><NAME>WIN2</NAME><OS>Windows 8</OS><DOMAIN>contoso.com</DOMAIN><IP>10.20.30.40</IP></HARDWARE>
awk 'BEGIN{ RS="[[:space:]]*</?HARDWARE>[[:space:]]*"
FS="[[:space:]]*<|</[^<>/]+>[[:space:]]*"
tn=split( "NAME OS IP DOMAIN", tag_order, " " )
}
$0 { delete tag
for( i=1;i<=NF;i++ ) if($i) { n=index($i,">"); tag[substr($i,1,n-1)]=substr($i,n+1) }
for( i=1;i<=tn;i++ ) printf "%s\t", tag[tag_order[i]]; print ""
}' file | column -ts$'\t'
산출:
WIN1 Windows 7 1.2.3.4 contoso.com
WIN2 Windows 8 10.20.30.40 contoso.com
답변4
with awk
- 각 열을 15자 길이로 임의로 설정하고 왼쪽 정렬하고 공백으로 채웁니다.
awk ' BEGIN { FS = "<[A-Za-z/]+>" } { if ( NR % 6 == 0 ) { printf"\n" } else if ( $2 != "" ) { printf"%-15s", $2 } }' file
또는 다른 답변과 같이 결합column
awk ' BEGIN { FS = "<[A-Za-z/]+>" } { if ( NR % 6 == 0 ) { printf"\n" } else if ( $2 != "" ) { printf"%s ", $2 } }' file | column -t