g/re/p를 사용하여 개행 문자를 바꾸는 것이 Vim의 다른 모든 줄에서만 작동하는 이유는 무엇입니까?

g/re/p를 사용하여 개행 문자를 바꾸는 것이 Vim의 다른 모든 줄에서만 작동하는 이유는 무엇입니까?

고려하다:

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/

관련 정보