gawk에서 혼합 개행 형식을 유지하는 방법은 무엇입니까?

gawk에서 혼합 개행 형식을 유지하는 방법은 무엇입니까?

Unix(LF) 및 Windows(CR/LF) 스타일 개행 문자가 포함된 입력 파일이 있습니다. (특히 Linux 시스템의 XML이지만 일부 원시 HTTP 헤더가 포함되어 있으며 HTTP는 헤더로 CRLF를 선호합니다.)

    <response_page cause="default">
      <response_type>custom</response_type>
      <response_header>HTTP/1.1 200 OK^M
Cache-Control: no-cache^M
Pragma: no-cache^M
Connection: close</response_header>

나는 이 파일을 반복하는 gawk 스크립트를 작성하여 XML*에 몇 가지 간단한 수정을 가하고 있습니다. 유일한 문제는 LF 및 CRLF 유효한 RS를 읽지만 거기에 무엇이 있든 관계없이 LF만 출력한다는 것입니다...본질, CR이 삭제됩니다.

나는 다양한 접근 방식을 시도했는데 그 중 가장 야심 찬 것은 RS에 대한 정규식 일치와 RT 인쇄입니다.

BEGIN { RS = "\r\n|\n"; go = "no" }
(go ~ /yes/) { 
    sub(/false/, "true", $0)
    go = "no"
}
($0 ~ /<signature signature_id="200000017">/) { 
    print "Found signature!"
    go = "yes"
} 
{ 
    printf $0 RT
}

혼합 플랫폼 RS 터미네이터를 재현하기 위해 멍청한 태도를 취하는 데 대한 조언에 정말 감사드립니다.

* 이 경우 간단한 조정은 올바른 서명 ID가 있는 행 다음 행에서 "false"를 "true"로 변경하는 것입니다. 나는 XML 파서를 사용하는 것이 이 작업을 수행하는 올바른 방법이라는 것을 충분히 알고 있지만 이러한 가벼운 요구 사항 때문에 XML 파싱의 고통과 불안감을 피하려고 노력하고 있습니다.

고쳐 쓰다:

이 솔루션은 Linux에서 실행될 때 작동하는 것으로 나타났습니다. Windows에서 Cygwin gawk에서 실행할 때 CRLF/LF 구분이 분명히 음소거되어 예상대로 작동하지 않습니다. 나는 Peter.O에게 답변 포인트를 부여합니다. 비록 그가 내가 시도했던 것을 본질적으로 다시 말했지만 그는 철저한 방식으로 그렇게 했기 때문에 우리가 똑같은 일을 하고 있고 내 것이 작동하지 않는다는 것을 깨닫게 했기 때문에 나는 내 가정에 의문을 제기합니다.

답변1

내장 변수를 사용할 수 있습니다RT

RT는 레코드를 읽을 때마다 설정됩니다. RS(Record Separator)로 표시되는 텍스트와 일치하는 입력 텍스트가 포함되어 있습니다. 이 변수는 gawk 확장입니다.

printf '%s\n' LF CRLF$'\r' | 
  gawk 'BEGIN { RS = "\r\n|\n" }
       { printf($0 RT) }'

파이프로 연결될 때 출력 sed -n l- 표시CR~처럼\r, 그리고end-of-line~처럼$- 어느 쪽으로sed다음 문자가 있음을 나타냅니다.\n(또는end-of-input.

LF$
CRLF\r$

그러나 종결자를 CRLF에서 LF로 또는 그 반대로 전환하려는 경우 다음 두 가지 작업이 있습니다.

printf '%s\n' was-LF was-CRLF$'\r' | 
  gawk 'BEGIN { RS = "\r\n|\n" }
        RT == "\r\n" { printf($0 "\n") }
        RT == "\n"   { printf($0 "\r\n") }'

파이프로 연결될 때 출력sed -n l

was-LF\r$
was-CRLF$

if참고: 테스트가 (기본) 코드의 첫 번째 줄이 아닌 경우 이를 사용해야 합니다.

  gawk 'BEGIN { RS = "\r\n|\n" }
        { # some processing code here (before the tests)
          if( RT == "\r\n" ) { printf($0 "\n") }
          if( RT == "\n")    { printf($0 "\r\n") } }'

답변2

간단한 해결책은 LF를 라인 끝으로 처리하고 최종 CR(있는 경우)을 꺼내서 인쇄하는 것입니다.

{ CR = (sub(/\r$/,"") ? "\r" : "") }
… { … print "stuff" CR }

마지막 입력 라인이 종료되지 않더라도 출력은 항상 LF로 끝납니다.

관련 정보