일치하는 후속 라인을 기반으로 파일 라인에서 특정 필드를 추출하는 방법

일치하는 후속 라인을 기반으로 파일 라인에서 특정 필드를 추출하는 방법

직장 문제를 재현하려고 합니다. 아래와 같이 xml 파일이 있습니다.

[~]$ less -N sample.xml
  1     <SOURCE BUSINESSNAME ="" NAME ="TABLE1" FOO="ABCD"..... >
  2         <SOURCEFIELD BUSINESSNAME ="" NAME ="COL_XYZ" />
  3         <SOURCEFIELD BUSINESSNAME ="" NAME ="COL_ABCD" />
  4         ...
  5                 ...
  6     </SOURCE>
  7     <SOURCE BUSINESSNAME ="" NAME ="TABLE2" ....... >
  8             <SOURCEFIELD BUSINESSNAME ="" NAME ="COL_ABCD" />
  9         <SOURCEFIELD BUSINESSNAME ="" NAME ="COL_XYZABC" />    
 10         ...
 11                 ...
 12     </SOURCE>
 13         <SOURCE BUSINESSNAME ="" NAME ="TABLE3" .... >
 14         <SOURCEFIELD BUSINESSNAME ="" NAME ="COL_PQR" />
 15         <SOURCEFIELD BUSINESSNAME ="" NAME ="COL_ABCD" />
 16         ...
 17                 ...
 18     </SOURCE>

이제 나는 그들 중 하나와 유사한 필드의 값을 원합니다 NAME.SOURCEFIELD NAMEXYZ

예를 들어, 주어진 예에서는 2번째 줄 에 TABLE1을 포함 해야 합니다 COL_XYZ.TABLE29COL_XYZABC

1,2,7,9,13행을 출력으로 가져온 다음 grep -B1 XYZ|grep -w SOURCE필드에서 1,7출력의 행을 가져오는 방법을 생각 중입니다 .

Expected Output:
TABLE1
TABLE2

내가 지금까지 시도한 것

  • SOURCE모든 줄에 이들 중 하나 이상이 포함되어 있으므로 grep을 실행해도 작동하지 않습니다.
  • egrep -w "SOURCE|XYZ"내 필요에 맞지 않는 일을 하는 것은 XYZABC그 조건을 만족시키지 못할 것입니다.

원하는 결과를 얻기 위해 무엇을 시도할 수 있는지 제안해 줄 수 있는 사람이 있나요? 나는 사용하고있다Linux 2.6.18-371.el5

답변1

hold space이 기능을 사용하면 이 작업을 수행할 수 있습니다 sed.

sed-n입력 라인의 자동 인쇄를 비활성화하는 옵션 으로 실행하십시오.

<SOURCE포함된 줄이 보이면 저장하세요.속성 의 NAME.sedhold space

<SOURCEFIELD포함된 행이 보일 때 XYZ인쇄되는 내용입니다 hold space.

#!/bin/sh

sed -n '
    /<SOURCE / {              # execute block {} on lines matching "<SOURCE "
        s/.* NAME *="//       # remove everything upto NAME attribute value
        s/".*//               # remove everything after attribute value
        h                     # copy pattern space to the hold space
    }
    /<SOURCEFIELD.*XYZ/ {     # SOURCEFIELD contains XYZ, execute {} block
        g                     # copy hold space to pattern space
        p                     # print
    }
' "$@"

답변2

sed -netP -eH            -e'# Hold every line and test for s///uccess' \
    -e'\|<[^F]*[ >]|!d'  -e'# if < then F before [ >]: delete'         \
-ex -e'\|_XYZ[^_]*>|!d'  -e'# first exchange buffers; if !XYZ: delete' \
    -e's|[^"]*|\n&\n|4'  -e'# wrap 4th no quotes series in newlines'   \
    -e'D;:P' -eP         -e'# Delete up to first newline, :Print if true'

TABLE1
TABLE2

...추가할 때XYZ세 번째 목록의 마지막 필드로,TABLE3인쇄도...

답변3

감사해요로버트 L이를 위해답변.

grep/awk/sed나는 또한 동일한 결과를 얻을 수 있는 조합을 생각해 냈지만 분명히 속도가 느립니다. 그냥 거기에 넣고 싶었어요.

egrep -w ""\<SOURCE"|"SOURCEFIELD.*XYZ.*"" sample.xml|grep -B1 XYZ|grep -w SOURCE|\                                                              
> awk -F" NAME =" '{print $2}'|awk '{print $1}'|sed 's/"//g'

관련 정보