다음과 같은 파일이 있습니다
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
다음 줄이 내용으로 시작하는지 확인하기 위해 이전 줄의 인쇄를 지연시킵니다 .)ABC
END
그런 다음 행을 두 개의 별도 변수에 복사하고
pre
(dpre
그 중 하나는 변경되지 않고 유지됩니다(나중에 변경되지 않고 인쇄해야 함), 다른 변수에는sub(/ {0,3}/,"END ", dpre)
문자열END
을dpre
.{0,4}
(0 또는 최대 4개의 공백, 4는 의 길이에서 얻음END<SPC>
) 를 사용하면END
문자열이 항상 앞에 추가되고 공백이 전혀 없는 경우 원래 줄 값이 잘리는 것을 방지할 수 있습니다.
이해를 돕기 위해 아래 명령의 각 반복을 추적할 수 있습니다.
- 반복하다
- 한 줄을 읽으십시오.
ABC
(/^ABC/
)?- 아니요; 아무것도 하지 않으면 다음 블록이 실행됩니다.두 번째 작품
- 예; 설정됐나요
pre
?- 예, 그런 다음 다음 작업을 수행하세요.
- 변수의 내용
dpre
, 단일 개행 문자ORS
, 현재 행 자체를 인쇄합니다. - 변수를 비우고
pre=""
다음으로 점프반복하다왜냐하면next
성명서가 그것을 말해주기 때문입니다.
- 변수의 내용
- 아니요; 아무것도 하지 않으면 다음 블록이 실행됩니다.두 번째 작품
- 예, 그런 다음 다음 작업을 수행하세요.
- 두 번째 작품
- 설정 됐나요
pre
?- 예; 이것들을 해라
- 인쇄 설정은 " "
pre
에 있습니다 .if(pre) print pre
- 현재 행을 두 개의 변수로 업데이트합니다
pre=dpre=$0
. - 접두사
END
끈dpre
.
- 인쇄 설정은 " "
- 아니요; 이것들을 해라
- 현재 행을 두 개의 변수로 업데이트합니다
pre=dpre=$0
. - 접두사
END
끈dpre
.
- 현재 행을 두 개의 변수로 업데이트합니다
- 예; 이것들을 해라
- 설정 됐나요
- 파일 끝이면
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
현재 레코드의 자동 인쇄가 켜져 있는 후루룩 모드에서는 -p
ABC 또는 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입니까? - 교체를 수행합니다. 둘러보기는 데이터를 소비하지 않고 일치하는 위치를 주장한다는 점을 이해합니다.