나의 궁극적인 목표는 문장 구분 기호를 기준으로 텍스트를 분할하는 것입니다. 그러나 문장으로 나누지 말고 덩어리로 나누어야 합니다. 1000줄과 현재 문장의 나머지 부분. 하지만 아래 실험에서는 단순화를 위해 2개의 행만 사용했습니다.
VIM 버퍼에서 다음 텍스트를 고려하세요.
line 1. line 1. line 1.
line 2. line 2. line 2.
line 3. line 3. line 3.
line 4. line 4. line 4.
line 5. line 5. line 5.
실행 후:
:2 | exec 'normal! )hvgg' | exec "'<,'>w /tmp/part1.txt" | exec 'normal! gvd'
결과는 예상대로입니다. 버퍼에는 다음이 포함됩니다.
line 2. line 2.
line 3. line 3. line 3.
line 4. line 4. line 4.
line 5. line 5. line 5.
하지만 다음 실행 후에
:2 | exec 'normal! )hvgg' | exec "'<,'>w /tmp/part2.txt" | exec 'normal! gvd'
버퍼에는 다음이 포함됩니다.
line 2.
line 3. line 3. line 3.
line 4. line 4. line 4.
line 5. line 5. line 5.
여기서 무슨 일이 일어나고 있는 걸까요? 왜 두 번째 행으로 이동하지 않습니까 line 3. line 3. line 3.
?
하지만 다음 텍스트가 버퍼에 남아 있기를 원합니다.
line 3. line 3.
line 4. line 4. line 4.
line 5. line 5. line 5.
답변1
문제의 근본은 gv
끝에 있습니다. 시각적 선택은 여전히 명령의 이전 부분에서 나오므로 이는 필요하지 않습니다. 더 나쁜 점은 gv
이미 시각적 모드에 있을 때 수행하기 때문에 이것이 무해하지 않다는 것입니다.현재 및 이전 시각적 영역 교환. 이전 선택이 다시 선택된다는 의미입니다!
이전 선택 항목이 삭제된 경우에도 선택 항목은 동일한 영역 또는 적어도 나머지 영역에 적용됩니다. 이 경우 line 2.
나머지 문장 중 첫 번째 문장 이 됩니다 .
시연하려면 다음과 같이 두 번 입력하면 어떤 일이 발생하는지 관찰해 보세요 2G)hvgggvd
. 이는 디스크 쓰기를 제외하고 100% 일반 모드 명령을 사용하여 명령줄에서 일어나는 일입니다.
어쨌든 우리는 gv
그것을 잃어버리면 됩니다:
:2 | exec 'normal! )hvgg' | exec "'<,'>w! /tmp/part1.txt" | exec 'normal! d'
그 외에도 명령에는 정리할 수 있는 잡음이 많이 있습니다. 두 개의 exec
와 그에 따른 따옴표는 필요하지 않습니다.
:2 | exec 'norm! )hvgg' | '<,'>w! /tmp/part1.txt | norm! d
고쳐 쓰다:귀하의 의견 중 하나에 대한 응답으로 ...
'<,'>
첫 번째 항목부터 선택하여 한 줄씩 작업하는 것입니다.철사마지막으로 선택한 보기 영역 - 지속철사같은 지역의. 문자 범위를 얻으려면 다음과 같이 백틱을 사용해야 합니다.
`<,`>
그러나 이것은 작동하지 않습니다 :w
. 단지 한 줄씩 작동할 뿐입니다.
이것이 특정 텍스트가 삭제된 이유를 묻는 귀하의 질문 범위를 벗어난다는 점을 지적하고 싶습니다. 따라서 파일을 문자별로 작성하는 것에 대해 별도의 질문을 할 수도 있습니다.
업데이트 2:문제에 대한 완전히 다른 접근 방식이 있습니다 ...
다음 명령을 사용하여 매크로를 만듭니다.
:let @q = ")hs\<CR>\<ESC>k:let @a=@a+1\<CR>:1,.w /tmp/part\<C-R>a.txt\<CR>dgg"
- 다음 명령을 실행하세요:
:let @a = 0
. - 문장 위에 커서를 놓고 일반 모드에서 매크로를 실행합니다.
@q
이는 설명하신 대로 정확하게 작동합니다. 문장과 그 위의 모든 내용이 이름이 지정된 파일에 기록되고 /tmp/part1.txt
저장된 텍스트는 삭제됩니다. 이제 다른 문장으로 이동하여 @q
다시 실행하십시오. 이번에는 동일한 일이 발생하지만 /tmp/part2.txt
매크로를 실행할 때마다 파일 이름이 자동으로 증가됩니다. 를 사용하여 인덱스를 다시 재설정할 수 있습니다 :let @a = 0
.
이전 업데이트와 마찬가지로 실제 질문에 대한 답변은 아니지만 친절하기 때문에 몇 가지 추가 도움을 제공하고 있습니다.(OP는 여전히 내 답변을 받아들이지 않습니다.)
답변2
마침내 허용되는 솔루션을 찾았습니다. 협조해 주신 @B Layer에게 감사드립니다(예: 명령은 w
파일에 전체 줄만 쓴다고 언급). 귀하의 답변에 투표했습니다.
:let i=1
:1000 | exec 'normal! )hvggd' | exec 'if i<10 | let num="0" . i | else | let num=i | endif' | call writefile(split(@@, "\n", 1), '/tmp/test' . num . '.txt') | let i=i+1
이후 @:
마지막 블록이 1000줄보다 짧을 경우 명령 반복을 누르면 오류 메시지가 표시됩니다. 나머지는 수동으로 저장하면 됩니다.
5번의 실행 후에 예상된 결과를 얻었습니다.
$ wc -l /tmp/test*.txt
1001 /tmp/test01.txt
1000 /tmp/test02.txt
1001 /tmp/test03.txt
1006 /tmp/test04.txt
1001 /tmp/test05.txt
사용하려는 분들을 위해 주요 단계를 간략하게 설명하겠습니다.
:1000
1000행으로 이동(블록 길이는 1000행 이상이어야 함)
exec 'normal! )hvggd'
다음 문장의 시작 부분으로 이동하고 한 문자 뒤로 이동하여 다음 문장의 첫 문자가 이후에 삭제되지 않도록 합니다. 여러 줄에 걸쳐 있는 문장을 올바르게 처리하려면 whichwrap=h,l
이 옵션을 설정해야 하며, 내가 아는 한 이는 기본값이 아닙니다. 현재 커서 위치부터 처음까지 모두 선택하여 삭제합니다. 삭제된 내용은 등록부에 저장됩니다.
call writefile(split(@@, "\n", 1), '/tmp/test' . num . '.txt')
레지스터 내용(블록)을 파일에 쓰기
내 가정은 99개 이상의 블록이 없을 것이라는 것입니다. 더 필요한 경우 패딩 관련 부분을 필요에 따라 조정하세요.