카테고리 보관물: vi

vi

각 경기를 증분 카운터로 바꾸는 방법은 무엇입니까? 싶습니다 . 카운터를 늘리는 것이 아니라 각 금액을

특정 패턴의 각 항목을 검색하고 1각 일치마다 하나씩 증가 하는 10 진수로 바꾸고 싶습니다 .

카운터를 늘리는 것이 아니라 각 금액을 고정 금액으로 수정하는 것과 비슷한 단어로 된 질문을 찾을 수 있습니다. 다른 유사한 질문은 증분 카운터 대신 행 번호를 삽입하는 것에 관한 것입니다.

예를 들면 다음과 같습니다.

#1
#1.25
#1.5
#2

후:

#1
#2
#3
#4

내 실제 데이터에는 다시 번호를 매길 물건 주위에 더 많은 텍스트가 있습니다.



답변

상태로 대체해야합니다. SO에 대한 이러한 종류의 문제에 대한 (/ 여러?) 완전한 솔루션 을 제공 한 것을 기억 합니다.

다음은 또 다른 방법입니다 (1). 이제 2 단계로 진행하겠습니다.

  • 내가 사용할 더럽고 복잡한 트릭에 필요한 더미 목록 변수
  • 이 더미 배열의 len을 삽입하는 치환은 각 일치하는 항목을 채 웁니다.

다음을 제공합니다.

:let t=[]
:%s/#\zs\d\+\(\.\d\+\)\=\ze/\=len(add(t,1))/g

정규 표현식을 vim하는 데 익숙하지 않은 경우 일치하는 하위 패턴을 사용 :h /\zs하고 \ze지정하기 위해 가능한 한 일련의 숫자와 점 및 기타 숫자가 일치합니다. 이것은 부동 소수점 숫자에 완벽하지는 않지만 여기서는 충분합니다.

참고 : 간단한 인터페이스를 위해서는 몇 가지 기능 + 명령으로 마무리해야합니다. 다시, SO / vim ( here , here , here ) 에 대한 예가 있습니다. 요즘에는이 트릭을 명령에 래핑하는 것에 신경 쓰지 않을 정도로 vim이 충분하다는 것을 알고 있습니다. 실제로 첫 번째 시도 에서이 명령을 작성할 수 있지만 명령의 이름을 기억하는 데 몇 분이 걸립니다.


(1) 목표는 대체 사이의 상태를 유지하고 현재 발생을 현재 상태에 의존하는 것으로 대체하는 것입니다.

덕분에 :s\=계산 결과를 삽입 할 수 있습니다.

국가의 문제를 유지합니다. 외부 상태를 관리하는 함수를 정의하거나 외부 상태를 업데이트합니다. C (및 관련 언어)에서는 length++or 와 같은 것을 사용할 수 있습니다 length+=1. 불행히도, vim 스크립트에서는 +=즉시 사용할 수 없습니다. 그것은 함께 사용될 수 필요 :set하거나 함께 :let. 즉 :let length+=1, 숫자 가 증가하지만 아무것도 반환하지 않습니다. 우리는 쓸 수 없습니다 :s/pattern/\=(length+=1). 우리는 다른 것이 필요합니다.

뮤팅 기능이 필요합니다. 즉, 입력을 변경하는 기능. 우리는이 setreg(), map(), add()아마 더합니다. 그들부터 시작합시다.

  • setreg()레지스터를 변경합니다. 완전한. setreg('a',@a+1)@Doktor OSwaldo의 솔루션에서와 같이 작성할 수 있습니다 . 그러나 이것은 충분하지 않습니다. setreg()(Pascal, Ada …를 아는 사람들 중) 이것은 아무것도 반환하지 않음을 의미합니다. 실제로는 무언가를 반환합니다. 명목 이탈 (예 : 비 예외 이탈)은 항상 무언가를 반환합니다. 기본적으로 무언가를 반환하는 것을 잊었을 때 0이 반환 되며 내장 함수에도 적용됩니다. 그래서 그의 솔루션에서 대체 표현은 실제로 \=@a+setreg(...)입니다. 까다 롭지 않습니까?

  • map()또한 사용될 수있었습니다. 단일 0 ( :let single_length=[0]) 으로 목록에서 시작 하면로 인해 증가 할 수 있습니다 map(single_length, 'v:val + 1'). 그런 다음 새 길이를 반환해야합니다. 달리 setreg(), map()그 돌연변이 입력을 반환합니다. 완벽합니다. 길이는 목록의 첫 번째 (고유 한 마지막 위치) 위치에 저장됩니다. 대체 표현식은입니다 \=map(...)[0].

  • add()내가 습관적으로 자주 사용하는 것입니다 map(). 아이디어 add()는 목록을 현재 상태로 사용하고 각 대체 전에 끝에 무언가를 추가하는 것입니다. 나는 종종 새로운 값을 목록의 끝에 저장하고 대체를 위해 사용합니다. 으로 add()또한 돌연변이 입력 목록을 반환, 우리가 사용할 수 있습니다 \=add(state, Func(state[-1], submatch(0)))[-1]. OP의 경우 지금까지 몇 개의 일치 항목이 감지되었는지 기억하면됩니다. 이 상태 목록의 길이를 반환하면 충분합니다. 따라서 내 \=len(add(state, whatever)).


답변

 :let @a=1 | %s/search/\='replace'.(@a+setreg('a',@a+1))/g

그러나 레지스터를 덮어 씁니다 a. 나는 그것이 luc의 대답보다 조금 더 직설적이라고 생각하지만 어쩌면 그의 것이 더 빠를 수도 있습니다. 이 솔루션이 그의 솔루션보다 나쁘다면 그의 답변이 더 나은 이유에 대한 의견을 듣고 싶습니다. 답변을 개선하기위한 모든 의견은 대단히 감사하겠습니다!

(또한 /programming/43539251/how-to-replace-finding-words-with-the-different-in-each-occurrence-in-vi-vim 의 SO 답변을 기반으로합니다. -edi / 43539546 # 43539546 )


답변

나는 2 년 전에 물었던 유사하지만 다른 질문을 발견하고 내가하고있는 일을 완전히 이해하지 않고 그 답 중 하나를 바꿀 수 있었고 훌륭하게 작동했습니다.

:let i = 1 | g/#\d\+\(\.\d\+\)\=/s//\=printf("#%d", i)/ | let i = i+1

특히 나는 왜 내 것이 사용되지 않는지 %또는 왜 다른 대답이 어떤 이유로 피하는 일반 변수를 사용하는지 이해하지 못합니다 .


답변

이 페이지 에는 이미 세 가지 훌륭한 답변 이 있지만 Luc Hermitte가 의견에서 제안한 것처럼 커프를 수행하는 경우 중요한 것은 작업 솔루션을 쉽고 빠르게 시작할 수 있다는 것입니다.

따라서 이것은 실제로 전혀 사용하지 않는 문제입니다 :substitute. 일반적인 일반 모드 명령과 재귀 매크로를 사용하여 쉽게 해결할 수있는 문제입니다.

  1. (필요한 경우) 먼저을 끕니다 'wrapscan'. 우리가 사용할 정규 표현식은 원하는 결과 텍스트와 초기 텍스트를 일치 시키므로 'wrapscan'매크로를 계속 사용하면 매크로가 계속 재생됩니다. (또는 무슨 일이 일어나고 있는지 알 때까지을 누르십시오 <C-C>.) :

    :set nowrapscan
    
  2. 기존 답변에서 이미 언급 한 것과 동일한 기본 정규식을 사용하여 검색어를 설정하십시오.

    /#\d\+\(\.\d\+\)\?<CR>
    
  3. (필요한 경우) 필요한N 만큼 여러 번 눌러 첫 번째 경기로 돌아갑니다 .

  4. (필요한 경우) 첫 번째 일치 항목을 원하는 텍스트로 변경하십시오.

    cE#1<Esc>
    
  5. "q레지스터를 지우고 매크로 기록을 시작하십시오.

    qqqqq
    
  6. 현재 카운터 Yank :

    yiW
    
  7. 다음 경기로 이동 :

    n
    
  8. 현재 카운터를 방금 막은 카운터로 교체하십시오.

    vEp
    
  9. 카운터를 늘리십시오.

    <C-A>
    
  10. 매크로를 재생 q합니다. "q5 단계에서 지운 레지스터 가 여전히 비어 있으므로이 시점에서 아무 일도 일어나지 않습니다.

    @q
    
  11. 매크로 기록을 중지하십시오.

    q
    
  12. 새로운 매크로를 재생 해보세요!

    @q
    

모든 매크로와 마찬가지로 위에서 설명한대로 설명하면 많은 단계처럼 보이지만 실제로 입력하는 것은 매우 빠릅니다. 재귀 매크로 기록 보일러 플레이트와 별개로 모두 규칙적입니다. 편집 명령 편집하는 동안 항상 수행하고 있습니다. 내가 생각에 접근 하는 것조차도해야 할 유일한 단계 는 2 단계였습니다. 여기서 검색을 수행하기 위해 정규 표현식을 작성했습니다.

이 명령 줄 모드 명령과 키 입력의 일련의 포맷, 이러한 유형의 솔루션의 속도는 더욱 분명해진다 : 나는 그것을 입력 할 수있는 나는 최대한 빨리 거의 다음을 연상 수 1 :

:set nowrapscan
/#\d\+\(\.\d\+\)\?
cE#1<Esc>qqqqqyiWnvEp<C-A>@qq@q

아마도이 페이지의 다른 솔루션을 약간 생각하고 문서 2를 참조하여 생각해 낼 수 있었을 것입니다. 하지만 매크로가 어떻게 작동하는지 이해하면 일반적으로 편집하는 속도에 관계없이 실제로 쉽게 벗어날 수 있습니다.

1 :이 있습니다 매크로 더 많은 생각을 요구하는 경우가 있지만, 나는 그들이 실제로 많이 올라 오지 않는 찾을 수 있습니다. 그리고 일반적으로 발생하는 상황은 매크로가 유일한 실용적인 해결책입니다.

2 : 다른 응답자가 비슷한 방식으로 솔루션을 쉽게 만들 수 없다는 것을 암시하지 않습니다. 그들은 개인적으로 쉽게 할 수없는 기술 / 지식 만 있으면됩니다. 그러나 모든 Vim 사용자는 정기적 인 편집 명령 사용법을 알고 있습니다!


답변