줄 순서를 바꾸는 방법?


24

첫 번째 줄이 끝에 나타나고 마지막 줄이 먼저 나타나도록 줄 순서를 바꾸려면 어떻게해야합니까? (버퍼의 모든 라인, 주소 범위 또는 라인 단위 비주얼 모드 선택 일 수 있습니다.)

변신하고 싶습니다

rat
ox
tiger
⋮
dog
pig

으로

pig
dog
⋮
tiger
ox
rat

와 같은 외부 명령에 의지하지 않고 tac.


이 질문에 더 나은 태그에 대한 제안 사항이 있습니까?
200_success

1
새로운 'pure-vi'또는 이와 유사한 태그일까요? 외부 도구를 사용하지 않으려는 태그를 통해 얻을 수있는 몇 가지 질문을 보았습니다. 메타에 대해 물어봐야합니까?
John O'M.

1
@Carpetsmoker (그리고 이것에 관심이있는 다른 사람들) 태그 질문은 이제 meta meta.vi.stackexchange.com/questions/1229/…
John O'M에 있습니다.

답변:


29

글로벌의 힘은 여기에서 작동합니다 :

:g/^/exe "normal ddggP"

또는 더 간단히 말하면 (@tommcdo 덕분에)

:g/^/move 0

첫 번째는 모든 행과 각 행과 일치하며 삭제하고 파일 맨 위에 붙여 넣습니다. 파일을 이동할 때 텍스트를 반대로 바꿉니다.

두 번째는 마찬가지로 모든 줄과 일치하여 파일의 맨 위로 이동합니다.

참고 :이파일전체 파일 에서 작동 하며 행의 서브 세트를 뒤집는 데 올바르게 적용되지 않습니다. 범위 내에서 작동하는 솔루션에 대해서는 Ingo Karkat의 답변 을 참조하십시오 .

기술:

g글로벌 명령은
/^/시작에 (즉, 모든 선)이있는 라인과 일치하는
exe다음 문자열을 실행
"normal일반 모드 명령을 수행
dd삭제 라인
gg파일의 상단으로 이동
P현재 위치 위에 붙여 넣기

move 0 현재 행을 0 행 아래로 이동합니다 (1 위치 또는 파일의 첫 번째 행에 위치)


6
:normal명령 대신 Ex 명령을 사용 :move 0하면 행이 버퍼의 시작 부분으로 이동합니다.
tommcdo

1
또한 :execute명령을 동적으로 빌드해야하는 경우에만 필요합니다 (예 :) :execute 'normal' g:user_command.
tommcdo

@tommcdo 좋은 포인트! 나는 :execute기존의 명령 후에 다른 Ex 명령을 종종 추가하기 때문에 사용 습관이 있습니다 :exe. 나중에 나중에 다시 삽입 해야하는 것보다 이미 거기 에있는 것이 더 편리합니다 . 불행히도, 그 습관은 그 답이 많이 적용되지 않는 곳에서이 답변으로 유출되었습니다.
John O'M.

1
내 사용에 대한 자세한 설명 :execute: 문자열을 사용하기 때문에 문자열을 구성하지 않더라도 일반 모드 명령이 끝나는 위치를 명확하게 설명합니다. 찾는 것보다 균형 잡힌 따옴표를 찾는 것이 더 쉽습니다. <esc>또는 모드를 종료하기 위해 무엇이든. 다시, 이것은 개인적인 취향과 습관입니다. :-)
John O'M.

3
이것은 btw 범위에서 작동합니다 : :9,11g/^/move 8... 마지막 숫자는 범위 -1의 시작이어야합니다 (Ingo의 대답에서 적응).
Martin Tournoij

13

이 one-liner ( ~/.vimrc)는 :Reverse명령을 정의합니다 . :global부품을 직접 사용할 수도 있지만 :move(범위 시작 전에 줄을 반복적으로 이동시켜 반전시키는) 구문은 기억하기 쉽지 않습니다.

:command! -bar -range=% Reverse <line1>,<line2>global/^/m<line1>-1

1
독자를위한 참고 자료로서 <line1>& <line2>는이 작업을 다양한 범위에서 수행해야합니다 :7,9Reverse( 예 :의 기능은 또는 command아닙니다 ). 더 간단한 것도 작동하지만 전체 버퍼에만 적용됩니다.globalmove:command! -bar -range=% Reverse :global/^/m 0
Martin Tournoij

6

순수한 Vim :

:g/^/m0

설명:

에 따르면 :help multi-repeat, :g그 사촌 :v은 두 가지 방식으로 작동합니다.

첫 번째 패스 패스는 :g모든 행과 일치 {pattern}하며 두 번째 패스 (파일의 시작에서 시작하여 끝까지 진행되는 것으로 명백히 수행됨)는을 수행합니다 [cmd]. 위의 사용은 :g라인이 처리되는 순서를 이용합니다 (기술적으로 보장되지는 않지만 괜찮을 것입니다).

먼저 모든 줄을 표시 한 다음 첫 번째 표시된 줄을 파일의 상단으로 이동 한 다음 두 번째 줄을 파일의 상단으로 이동 한 다음 (이전에 이동 한 줄 위), 세 번째 표시된 줄 (이전에 이동 한 것 이상)으로 작동합니다 파일의 마지막 줄이 맨 위로 이동하여 파일을 효과적으로 되돌릴 때까지 계속 진행합니다.

:g위에서 아래로가 아닌 다른 순서로 행을 처리 하면 이 명령이 작동하지 않습니다.

출처 : vim wikia에서 모든 라인g 의 거듭 제곱을 바꾸십시오.

외부 명령을 사용하는 몇 가지 예 :

  • tac( GNU coreutils의 일부 - cat반대) :

    :%!tac                                                                                                                                                                                                                                                              
    
  • tail BSD / OSX (POSIX 호환 아님) :

    :%!tail -r
    

    -r -r 옵션을 사용하면 입력이 라인별로 역순으로 표시됩니다.

    man tar자세한 내용은 확인 하십시오.

자세한 아이디어는 다음을 참조하십시오.


2
하지인가 :g/^/m0와 같은 :g/^/move 0존의 대답 인?
muru

@muru 그렇게 생각하지만 이것은 vim wikia에 따르면 더 짧으며 명령 줄 사용에 대한 몇 가지 추가 예제로 다른 설명을 추가했습니다.
kenorb

예, 다른 명령으로 인해 투표했습니다 (게시물이 나왔습니다 tac). 그러나 나는 downvote가 답이 반복되기 때문이라고 생각합니다.
muru

나는 tacOP가 언급 한 것을 알고 있지만 다른 모든 유사한 질문은 이것과 중복 될 것이므로 다시 언급하는 것이 좋습니다. John은 @tommcdo 주석 에서이 cmd를 가져 왔으며 처음에는 DerMike 에서 가져 왔습니다 .하지만 단순히 Wikia에서 가져온 것으로 생각하므로 vim wikia에 크레딧을 주었으므로 설명이 완전히 다르기 때문에 완전히 복제되지 않았습니다.
kenorb

적절한 설명으로 훨씬 짧은 버전이므로 더 많은 가치가 추가되고 올바른 소스를 제공하고 있습니다. 쉘 명령을 사용하는 것은 매우 간단하고 편리합니다. 사람들이 동의하지 않으면, 단순히 투표권을 행사할 수 있습니다.
kenorb

6

기능성 VimL의 정신에서 :

:call setline(1, reverse(getline(1, line('$'))))
  • getline(1, line('$'))버퍼 내의 모든 행의리스트를 돌려줍니다. 버퍼의 마지막 행을 나타내는 '$'특수 인수입니다 line().
  • reverse(...)입력 목록을 제자리로 되돌립니다. 하나는 사용해야합니다 reverse(copy(...))입력 목록이 수정되지 않아야합니다.
  • setline(1, ...)지정된 줄을 두 번째 인수로 바꿉니다. 두 번째 인수가 목록 인 경우 목록의 길이와 동일한 행 수가 목록의 내용으로 바뀝니다.

원하는 경우 범위를 갖는 명령을 정의 할 수도 있습니다 (기본 %전체 버퍼).

:command! -bar -range=% Reverse call setline(<line1>, reverse(getline(<line1>, <line2>)))

1
나는이 답변을 좋아한다. 또한 다른 답변 hlsearch:g/명령 과 같은 내용 ( 사용 가능한 경우 )을 강조 표시하지 않습니다 ...하지만 성능이 떨어질 수 있습니까? getline(1, line('$'))메모리의 전체 버퍼를 가져 오기 때문 입니다. reverse()제자리에있는 것처럼
보이므로

3

Vim 문서에 따라 usr_12.txt-Clever Tricks

12.4 역순

:global명령이와 결합 될 수있다 :move반전 된 파일의 결과로, 첫 번째 라인 전에 모든 라인을 이동하는 명령. 명령은 다음과 같습니다.

:global/^/m 0

약식 :

:g/^/m 0

^정규 표현식은 라인 (라인이 비어있는 경우에도)의 시작과 일치합니다. 이 :move명령은 일치하는 줄을 신화적인 0 번째 줄 다음으로 이동하므로 현재 일치하는 줄은 파일의 첫 번째 줄이됩니다. 는 AS :global명령이 변화하는 라인 번호에 의해 혼동되지 않으며, :global파일 및 첫 번째로 박았 각각의 남아있는 모든 라인을 일치로 진행한다.

이것은 또한 다양한 라인에서 작동합니다. 먼저 첫 번째 줄 위로 이동하여로 표시하십시오 mt. 그런 다음 커서를 범위의 마지막 줄로 이동하고 다음을 입력하십시오.

:'t+1,.g/^/m 't

1

상대 숫자를 사용합니다. 단락은 13 행에서 시작하여 4 행 이상 스팸

 :13,13+4g/^/m12
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.