검색 문자열을 기반으로 로그에서 xml을 추출하는 grep 또는 awk

검색 문자열을 기반으로 로그에서 xml을 추출하는 grep 또는 awk

XML이 기록되는 로그 파일이 있습니다. 모든 노드에 특정 문자열이 있는 모든 XML을 검색하고 추출해야 합니다.

예를 들어 로그 파일에는 검색 매개변수가 포함된 여러 XML이 있습니다.

randomlogentry1
randomlogentry2
Printing XML:<CreateDataABC>
    <Tag1>searchparam</Tag1>
</CreateDataABC>
randomlogentry3
randomlogentry4
randomlogentry5
Printing XML: <DataCreatedABC>
       <TagA>otherparam</TagA>
       <TagB>searchparam</TagB>
       <TagC>otherparam</TagC>
    </DataCreatedABC>
randomlogentry6
randomlogentry7

예상되는 출력은 콘솔에 인쇄되거나 별도의 파일에 작성된 두 개의 XML입니다.

XML1:

<CreateDataABC>
     <Tag1>searchparam</Tag1>
</CreateDataABC>

XML2:

<DataCreatedABC>
     <TagA>otherparam</TagA>
     <TagB>searchparam</TagB>
     <TagC>otherparam</TagC>
</DataCreatedABC>

XML에서 "searchparam"의 위치는 고정되지 않으며 유일한 상수는 "ABC" 문자열과 "searchparam"입니다.

sed를 사용하여 두 줄 번호 사이의 내용을 추출하고 싶습니다. 다음을 시도했습니다.

  1. 검색 매개변수를 검색하고 줄 번호를 식별합니다.
  2. ABC의 다음 발생을 찾아 줄 번호를 얻습니다.

특정 행에서 이전에 발생한 ABC를 찾을 수 없는 것 같습니다.

전에 이런 일을 해본 사람이 있나요?

편집: 예제 로그 형식 및 예상 출력이 업데이트되었습니다.

답변1

이 시도:

Max=`grep -c "^Printing" file.xml`

for count in `seq 1 $Max`
do
    sed -nr '/Printing/H;//,/ABC/G;s/\n(\n[^\n]*){'$count'}$//p'  file.xml | sed 's/Printing XML://' > $count.xml
done

답변2

이것이 내가 쓴 것이지만, 이 작업을 수행하는 더 짧고 우아한 방법이 있다고 확신합니다.

searchstring=searchparam
filename=test.log
pattern1=ABC

linenums=($(grep -n "${searchstring}" ${filename} | awk -F":" '{print $1}'))
len=${#linenums[@]}

for (( i=0; i<${len}; i++ ));
do
  currentline=${linenums[$i]}
  relativeendlinearray=($(tail -n +${currentline} ${filename} | grep -n "${pattern1}" | awk -F":" '{print $1}'))
  actualendline=$(($currentline+${relativeendlinearray[0]}-1))

  index=$currentline
  while [ $index -ne 0 ]
        do
        found=`sed "${index}q;d" ${filename} | grep "${pattern1}"`
        if [ -n "$found" ]; then
            actualstartline=$index
            break;
        fi
        index=$[$index-1]
  done

  if [ -n "$found" ]; then
        echo ""
  else
        echo "Log break detected, content across multiple files"
  fi

  echo "Start Line" ${actualstartline}
  echo "Current Line" ${currentline}
  echo "End Line" ${actualendline}
  sed -n "${actualstartline},${actualendline}p" ${filename}
done

관련 정보