고려하다:
foo
bar
....
bar
baz
그 다음에:
:g/bar/s/\n/\r\r/g
예상치 못한 수익:
foo
bar
bar
bar
bar
bar
...
baz
각 뒤에 새로운 줄을 원할 때 bar
. 하지만:
:g/bar/p
반품:
bar
bar
...
bar
예상대로 모든 s 사이에 개행 문자가 있으면 bar
예상한 결과를 얻습니다. 각 줄에는 다음 bar
과 같은 방법으로 문제를 해결했습니다.
:%s/\(bar.*\)\n/\1\r\r/g
하지만 저는 무슨 일이 일어나고 있는지 더 잘 이해하고 싶습니다.
답변1
이 정도 수준의 세부적인 내용을 이해하려면 소스 코드를 가져와야 한다고 생각합니다. 따라서 인용하십시오 vim-7.1.314/src/ex_cmds.c
(헤더를 정의하는 주석 ex_global()
).
이는 두 가지 단계로 이루어집니다. 먼저 파일에서 패턴을 검색하고 일치하는(일치하지 않는) 각 줄에 플래그를 설정합니다. 둘째, 표시된 각 줄에서 명령을 실행합니다. 이는 행을 삭제한 후 다음 일치 항목을 검색할 위치를 알 수 없기 때문에 필요합니다.
따라서 'ed 명령에서 한 줄을 삭제하면 :g
해당 줄에 대한 표시도 사라집니다. 'ed 명령에 라인을 생성하면 :g
표시되지 않으므로 명령이 실행되지 않습니다. 예에서 행 3은 행 2에 연결되어 있으므로 행 3의 마커가 사라지고 행 2 다음의 마커는 원래 행 4에 배치된 마커입니다.
또한 변수가 ex_global
설정되어 일부 명령(포함 )이 약간 다르게 작동하게 global_busy
됩니다 . :s
하지만 여기서는 그 차이가 중요하지 않다고 생각합니다.
답변2
자일스이미 "왜?"에 답했지만, 원하는 것을 달성하기 위한 더 쉬운 방법에 관심이 있으실 거라고 생각했습니다.
나는 각각 다음에 새로운 줄을 원합니다
bar
.
줄 종결자 문자를 바꾸는 대신(따라서 줄을 연결하고 Giles의 답변에 따라 내부 토큰이 손실됨) 일치하는 각 줄의 끝 앞에 빈 줄을 추가하십시오. $
줄이 끝나기 전에 너비가 0인 일치 항목을 얻는 데 사용되며 거기에 개행 문자를 삽입합니다( /g
패턴은 줄당 한 번만 일치하므로 수정자가 필요하지 않습니다).
:g/bar/s/$/\r/