n 줄 삭제 한 줄 스크립트 건너 뛰기


10

단순히 n 줄을 삭제하고 1 줄을 건너 뛰고 문서 끝까지 반복하는 기본 Vim 스크립트를 만들고 싶습니다. 특정 경기에 신경 쓰지 않고 라인을 삭제하고 싶습니다. 예를 들어; 3ddj전체 문서에 대해 명령을 반복하고 싶습니다 .

Text I want to keep.   
Text I want to delete.  
Text I want to delete.  
Text I want to delete.  
Text I want to keep.  
Text I want to delete.  
Text I want to delete.  
Text I want to delete.  
Text I want to keep.  
Text I want to delete.  
Text I want to delete.  
Text I want to delete.   

그래서 마치 ...

Text I want to keep.  
Text I want to keep.  
Text I want to keep.  

감사합니다.


regular-expression질문에 태그 를 포함 했지만 질문에 정규 표현식으로이를 수행 할 이유를 지정하지 않은 것 같습니다. 실제로 정규식을 사용하는 것을 찾고 있다면 stackoverflow.com/questions/17735289/… 가 흥미로울 수 있습니다. 그 질문은 메모장 ++에 관한 것이지만 대답은 pcre 정규식 만 사용합니다. (면책 조항 : 나는 그 대답을 썼다.)
Jasper

다음에 질문 할 때는 "감사합니다. 훌륭한 솔루션입니다!"라고 쓸 필요가 없습니다. 모든 단일 답변에. 답변에 대한 새 의견을 작성하려고 할 때도 작성됩니다.
파이프

여기에 감사를 표시하는 올바른 방법은 자신에게 가장 적합한 답변을 수락하고 도움이되거나 유용한 답변을 찬성하는 것입니다. 사람들은 "감사"의견보다는 그 사실을 훨씬 더 많이 알 것입니다.
B 레이어

답변:


19

매우 간단한 접근법 :

  1. 삭제할 첫 번째 줄로 이동하십시오.
  2. 매크로를 기록하십시오. qa3ddjq
  3. 높은 수로 반복하십시오 : 1000 @ a

3 단계는 매크로를 천 번 또는 오류가 발생할 때까지 반복합니다. 파일 끝을 누르면 (따라서 삭제할 행이 없음) 오류가 발생하고 매크로 반복이 취소됩니다.

참조하십시오 :help recording.


2
그 놀라운!!! 정말 감사합니다, 저에게 도움이되었습니다 : D
Max Copley

1
설명 : q(명령 모드 및 vim 또는 다른 최신 대체 버전 (neovim 등) (원래 vi에는 없음))은 "녹화를 시작하고 '다음 문자'버퍼에 넣습니다"를 의미합니다. 따라서 : qa" 'a'버퍼에 기록 시작"을 의미합니다. 그런 다음 q명령 모드 에서 다음 에 입력 할 때까지이 키를 입력 한 모든 키 가 기록됩니다 (편집 모드로 들어가기, 무언가 타이핑하기, 명령 모드로 나가기 등). 그런 다음 12@a버퍼 "a"에 기록 된 모든 작업을 12 번 반복합니다.
Olivier Dulac

3
또한 1000@q마지막 과 같은 것을 실행하고 싶지 않은 경우 재귀 매크로를 만들 수 있습니다. qa3ddj@aq@a하지만 시작을 비우 qaq려면 먼저해야 "a합니다.
제임스

17

나에게 가장 쉬운 해결책은 다음과 같습니다.

:%norm j3dd

그건:

  • %: 모든 라인
  • norm: 일반 모드 에서처럼 다음 키를 실행하십시오.
  • j3dd: 온라인으로 내려간 다음 3 줄을 삭제하십시오.

첫 번째 줄에서 두 번째 줄로 내려 가서 다음 3 줄을 삭제하십시오. 두 번째 Text I want to keep.는 이제 두 번째 줄에 있습니다. 한 줄 아래로 내려 가서 3. 헹구고 반복하십시오.


참고 : 전체 파일을 처리하지 않으려면 %norm5,$norm를 들어 5 번째 줄부터 파일 끝까지 처리 하도록를 바꿀 수 있습니다 .


4
아주 좋은 대안! vim에서 작동합니다 (vi가 아님). 나는 "규범"에 대해 들어 본 적이 없다! (그리고 나는 일종의 vi [m] 괴짜)
Olivier Dulac

6

이미 사용 가능한 훌륭한 솔루션이 있습니다. 다른 하나는 다음과 같습니다.

:g/^/if line('.')%4!=1|:s/^/DELETE ME/|endif
:g/^DELETE ME/d

먼저 모든 줄 :g에 대해 ^((줄의 시작과 일치) 작업을 수행하고 모든 줄 번호에 대해의 결과를 수행합니다 linenumber % 4. 결과가 같지 않으면 행의 시작 부분에 1추가 DELETE ME하여 다음 명령으로 삭제 될 행을 표시합니다.

다음 명령은 일반 ( :g) 명령으로 시작하고 시작하는 모든 줄과 일치합니다 DELETE ME.

첫 번째 :g명령을 사용하여 줄을 즉시 삭제할 수는 없습니다 . 결과 모듈로 계산이 변경되므로 먼저 줄을 표시하고 두 번째 단계에서 삭제해야합니다.


4

나는 이것이 vi채널 이라는 것을 알고 있지만, 이것은 sed문제입니다.

sed -ne 'p;n;n;n' <file >newfile

따라서 vi솔루션에 얽을 수 있습니다 .

:0
!Gsed -ne 'p;n;n;n'

1
sed 솔루션의 경우 +1
Christian Brabandt

3

대안 (1 줄에서 시작하여 예제 텍스트에 따라 2-4, 6-8 등을 삭제한다고 가정합니다) :

while line(".") < line("$")
    silent +1delete _ 3
endwhile

대화식으로이 작업을 수행하려면 "명령 줄 레지스터"를 사용할 수 있습니다. 즉,

:+1del 3<CR> 그리고 1000@:


1

대안 : 1, 4 등의 행을 유지하려고합니다. 다음을 사용할 수 있습니다.

awk '!((FNR-1)%3)'  file > newfile
      # awk: when a condition is given without action:
      #        prints the lines for which the condition returns 0.
      # FNR designates the line number in the current file.
      # a%3 : takes the modulus of a and 3. ( 0%3=0, 1%3=1, 2%3=2, 3%3=0, 4%3=1, etc.) 
      # This will be 0 for 3, 6, etc. 
      # But we want it to be 0 (true) for 1, 4, etc : so we substract 1 to NR

# to see that it keeps those lines:
seq 1 20 | awk '!((NR-1)%3)'
1
4
7
10
13
16
19

다른 대안 : 원하는 줄을 알고 있다면 고유 한 패턴과 일치합니다.

# for exemple each line you want contains "some pattern":
fgrep "some pattern" file > newfile
# (or regular grep if you want "some pattern" to be interpreted as a regexp)
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.