awk를 사용하여 행에서 열로

awk를 사용하여 행에서 열로

예제 출력을 따라야 합니다.

<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

관련 정보