지정된 문자열이 발견되면 줄을 수정합니다.

지정된 문자열이 발견되면 줄을 수정합니다.

다음과 같은 파일이 있습니다

ABC
     2   3   4
     7   9   4
     1   2   5
ABC
     13  11  17
     2   1   1
ABC
     7   9   14
     5   8   2
     9   9   9
     7   1   2

각 "ABC" 값 끝에 "END"라는 단어를 인쇄하고 싶으므로 파일은 다음과 같습니다.

ABC
     2   3   4
     7   9   4
END  1   2   5
ABC
     13  11  17
END  2   1   1
ABC
     7   9   14
     5   8   2
     9   9   9
END  7   1   2

많은 노력을 했지만 아무 효과가 없었습니다. 누구든지 도와주실 수 있나요?

답변1

awk '/^ABC/ && pre { print dpre ORS $0; pre=""; next }
                   { if(pre) print pre; pre=dpre=$0; sub(/ {0,4}/, "END ", dpre) }
END{ if(pre) print dpre }' infile

첫 번째 블록은 줄이 다음으로 시작하는 경우에만 실행됩니다.ABC 문자열 및 임시 변수pre또한 설정됩니다. 그렇지 않으면 다음 블록이 실행됩니다.

END{...}블록은 모든 작업이 완료된 후 한 번만 실행됩니다.

물론 첫줄은 아직pre변수가 아직 설정되지 않았으므로 다음을 수행하는 두 번째 블록이 실행됩니다.

  • 내용이 있으면 pre먼저 인쇄합니다. (이렇게 하면 해당 줄 앞에 추가 해야 하므로 if(pre) print pre다음 줄이 내용으로 시작하는지 확인하기 위해 이전 줄의 인쇄를 지연시킵니다 .)ABCEND

  • 그런 다음 행을 두 개의 별도 변수에 복사하고 pre( dpre그 중 하나는 변경되지 않고 유지됩니다(나중에 변경되지 않고 인쇄해야 함), 다른 변수에는 sub(/ {0,3}/,"END ", dpre)문자열 ENDdpre.

    {0,4}(0 또는 최대 4개의 공백, 4는 의 길이에서 얻음 END<SPC>) 를 사용하면 END문자열이 항상 앞에 추가되고 공백이 전혀 없는 경우 원래 줄 값이 잘리는 것을 방지할 수 있습니다.


이해를 돕기 위해 아래 명령의 각 반복을 추적할 수 있습니다.

  • 반복하다
  • 한 줄을 읽으십시오.ABC( /^ABC/)?
    • 아니요; 아무것도 하지 않으면 다음 블록이 실행됩니다.두 번째 작품
    • ; 설정됐나요 pre?
      • , 그런 다음 다음 작업을 수행하세요.
        • 변수의 내용 dpre, 단일 개행 문자 ORS, 현재 행 자체를 인쇄합니다.
        • 변수를 비우고 pre=""다음으로 점프반복하다왜냐하면 next성명서가 그것을 말해주기 때문입니다.
      • 아니요; 아무것도 하지 않으면 다음 블록이 실행됩니다.두 번째 작품
  • 두 번째 작품
    • 설정 됐나요 pre?
      • ; 이것들을 해라
        • 인쇄 설정은 " " pre에 있습니다 .if(pre) print pre
        • 현재 행을 두 개의 변수로 업데이트합니다 pre=dpre=$0.
        • 접두사ENDdpre.
      • 아니요; 이것들을 해라
        • 현재 행을 두 개의 변수로 업데이트합니다 pre=dpre=$0.
        • 접두사ENDdpre.
  • 파일 끝이면 dpre변수가 설정된 경우 최종 상태를 인쇄합니다.반복하다.
  • 마치다

답변2

$ cat tst.awk
NF == 1 { sub(/^   /,"END",prev) }
NR > 1 { print prev }
{ prev = $0 }
END { sub(/^   /,"END",prev); print prev }

$ awk -f tst.awk file
ABC
     2   3   4
     7   9   4
END  1   2   5
ABC
     13  11  17
END  2   1   1
ABC
     7   9   14
     5   8   2
     9   9   9
END  7   1   2

답변3

POSIX sed패턴 공간 자동 인쇄 끄기( -n)

sed -ne '
  /ABC/!{x;1!p;$!d;}
  x;1!s/^ \{0,3\}/END&/p
  ${x;/ABC/p;}
'  file
ABC
     2   3   4
     7   9   4
END  1   2   5
ABC
     13  11  17
END  2   1   1
ABC
     7   9   14
     5   8   2
     9   9   9
END  7   1   2   

위의 sed 코드를 확장하고 주석 처리하세요.

sed -ne '
  # if we see a non boundary line...
  /ABC/!{
    x;           # store it n retrieve prev line
    1!p;         # print the prev line if not first (obviously)
    $!d;         # printed prev so go back n read next line unless we are @eof(for which see below...)
  }
  x;                  # retrieve prev
  1!s/^ \{0,3\}/END&/p; # add marker
  ${x;/ABC/p;}
  # To account for a trailing ABC
'  file

답변4

진주이 상황에서 사용할 수 있으며 강력한 정규식 기능 덕분에 실제 줄로 정렬할 수 있습니다.

perl-0777현재 레코드의 자동 인쇄가 켜져 있는 후루룩 모드에서는 -pABC 또는 eof 줄 다음의 모든 줄을 확인합니다. 두 경우 모두 문자열 "END"가 시작 부분에 삽입되어 최대 3개의 공백 문자를 포함합니다.

perl -0777pe '
  s/^(?!ABC)\h{0,3}(?=.*\n(?:ABC|\z))/END/mg;
' file

정규식 연구:

  • ABC로 시작하지 않는 줄 찾기^(?!ABC)
  • 처음에는 공백이 3개 이상이어야 합니다(최소).\h{0,3}
  • 이 유리한 지점에서 현재 줄의 끝을 볼 수 있고 (?=.*\n(?:ABC|\z)거기에서 ABC로 시작하는 다음 줄을 볼 수 있습니까, 아니면 eof입니까?
  • 교체를 수행합니다. 둘러보기는 데이터를 소비하지 않고 일치하는 위치를 주장한다는 점을 이해합니다.

관련 정보