SED 또는 AWK를 사용하여 xml 파일에서 서로 다른 두 패턴과 일치하는 두 줄 복사

SED 또는 AWK를 사용하여 xml 파일에서 서로 다른 두 패턴과 일치하는 두 줄 복사

다음 유형의 줄이 포함된 큰 xml 파일이 있습니다.

<test type="one" valid="yes" description="something">
                    twilight-.*\.iso\.auth</test>

<test type="one" valid="no" description="something else">
                    testlite-.*\.cop</test>

<test type="two" valid="yes" description="something else">
                    messing-.*\.cop\.auth</test>
<test type="three" valid="yes" description="something else">messing-.*\.cop\.auth</test>

내 XML 파일에는 이와 같은 줄이 많이 있습니다. 내 요구 사항은 다음과 같습니다

  1. 첫 번째 줄의 "valid="yes"" 패턴과 두 번째 줄의 ".auth" 패턴이 일치하면 이 두 줄이 복사됩니다. 두 번째 줄에서 ".auth"를 ".newauth"로 바꿉니다.
  2. 같은 줄에서 "valid="yes"와 ".auth" 패턴이 일치하면 해당 줄을 복사하고 ".auth"를 ".newauth"로 바꾸세요.

출력은 다음과 같아야 합니다.

<test type="one" valid="yes" description="something">
                    twilight-.*\.iso\.auth</test>
<test type="one" valid="yes" description="something">
                    twilight-.*\.iso\.newauth</test>

<test type="one" valid="no" description="something else">
                    testlite-.*\.cop</test>

<test type="two" valid="yes" description="something else">
                    messing-.*\.cop\.auth</test>
<test type="two" valid="yes" description="something else">
                    messing-.*\.cop\.newauth</test>
<test type="three" valid="yes" description="something else">messing-.*\.cop\.auth</test>
<test type="three" valid="yes" description="something else">messing-.*\.cop\.newauth</test>

내 xml 파일에는 교체해야 할 여러 줄(쌍)이 있다는 점에 유의하세요. 그러나 교체 규칙은 위와 동일합니다. 또한 네 번째 줄의 경우 전체 xml 태그가 한 줄의 일부라는 점에 유의하세요. 따라서 이 경우 awk 표현식은 약간 더 복잡해집니다.

미리 감사드립니다!

답변1

수정된 질문에 맞춰 업데이트됨

이 시도. GNU awk 4.2.1에서는 잘 작동하는 것 같습니다.

awk '/valid="yes"/{print;if(!/<\/test>/){a=$0;getline;print $0"\n"a}gsub(/\.auth/,".newauth")}1' filename

답변2

다음과 같이 편집기를 사용하여 sed이 작업을 쉽게 수행할 수 있습니다 .

$ sed -e '
    /valid="yes"/!b
    h;/\.auth/G
    /\n/P;//s/.*\n//
    s/\.auth/.newauth/;t
    $q;N;/\.auth/!{P;D;}
    p;s//.newauth/
' test.xml

답변3

@Steve의 솔루션을 기반으로 한 2단계 프로세스를 통해 원하는 것을 달성할 수 있었습니다.

  1. 해결책 #1:
    awk '/valid="yes"/{print;a=$0; next} /.auth/{print $0"\n"a;gsub(/\.auth/,".newauth")}1' test.xml > newtest.xml
  1. 위 단계의 xml 파일을 사용하여 #2를 해결하세요.
    awk '/valid="yes"/ && /.auth/{print $0;gsub(/\.auth/,".newauth")}1' newtest.xml > final.xml

이 두 작업을 하나의 awk 작업으로 결합할 수 있습니까?

답변4

자신이 수행 중인 작업을 실제로 알고 있고 XML이 다른 형식일 수 없거나 문제를 포함할 수 없다면 두 단계나 복잡한 스크립트가 필요하지 않습니다. 이 작업은 한 번만 수행하면 됩니다.

sed -e '/valid="yes"/!b' -e '/\.auth/!N;p;s/\.auth/.newauth/'
  • /valid="yes"/!b패턴( )이 포함되지 않은 줄의 경우 b스크립트 끝으로 이동하므로 !다른 모든 내용은 그대로 유지됩니다.
  • /\.auth/!N!( )를 포함하지 않는 줄 에 적용됩니다 . 이 줄에는 ext 줄을 .auth추가합니다.N
  • p현재 패턴 공간을 인쇄합니다(한 줄 또는 두 줄일 수 있음). 어쨌든 필요에 따라 카피한다
  • s/\.auth/.newauth/필요한 교체를 수행합니다. 수정되지 않은 라인이 인쇄되었습니다 p. 이제 이를 반복하도록 수정하고 일반 처리가 끝나면 인쇄됩니다.
  • 5단계? 5단계는 없습니다.

관련 정보