첫 번째 줄이 끝에 나타나고 마지막 줄이 먼저 나타나도록 줄 순서를 바꾸려면 어떻게해야합니까? (버퍼의 모든 라인, 주소 범위 또는 라인 단위 비주얼 모드 선택 일 수 있습니다.)
변신하고 싶습니다
rat
ox
tiger
⋮
dog
pig
으로
pig
dog
⋮
tiger
ox
rat
와 같은 외부 명령에 의지하지 않고 tac
.
첫 번째 줄이 끝에 나타나고 마지막 줄이 먼저 나타나도록 줄 순서를 바꾸려면 어떻게해야합니까? (버퍼의 모든 라인, 주소 범위 또는 라인 단위 비주얼 모드 선택 일 수 있습니다.)
변신하고 싶습니다
rat
ox
tiger
⋮
dog
pig
으로
pig
dog
⋮
tiger
ox
rat
와 같은 외부 명령에 의지하지 않고 tac
.
답변:
글로벌의 힘은 여기에서 작동합니다 :
:g/^/exe "normal ddggP"
또는 더 간단히 말하면 (@tommcdo 덕분에)
:g/^/move 0
첫 번째는 모든 행과 각 행과 일치하며 삭제하고 파일 맨 위에 붙여 넣습니다. 파일을 이동할 때 텍스트를 반대로 바꿉니다.
두 번째는 마찬가지로 모든 줄과 일치하여 파일의 맨 위로 이동합니다.
참고 :이 두 파일 은 전체 파일 에서 작동 하며 행의 서브 세트를 뒤집는 데 올바르게 적용되지 않습니다. 범위 내에서 작동하는 솔루션에 대해서는 Ingo Karkat의 답변 을 참조하십시오 .
기술:
g
글로벌 명령은
/^/
시작에 (즉, 모든 선)이있는 라인과 일치하는
exe
다음 문자열을 실행
"normal
일반 모드 명령을 수행
dd
삭제 라인
gg
파일의 상단으로 이동
P
현재 위치 위에 붙여 넣기
move 0
현재 행을 0 행 아래로 이동합니다 (1 위치 또는 파일의 첫 번째 행에 위치)
:normal
명령 대신 Ex 명령을 사용 :move 0
하면 행이 버퍼의 시작 부분으로 이동합니다.
:execute
명령을 동적으로 빌드해야하는 경우에만 필요합니다 (예 :) :execute 'normal' g:user_command
.
:execute
기존의 명령 후에 다른 Ex 명령을 종종 추가하기 때문에 사용 습관이 있습니다 :exe
. 나중에 나중에 다시 삽입 해야하는 것보다 이미 거기 에있는 것이 더 편리합니다 . 불행히도, 그 습관은 그 답이 많이 적용되지 않는 곳에서이 답변으로 유출되었습니다.
:execute
: 문자열을 사용하기 때문에 문자열을 구성하지 않더라도 일반 모드 명령이 끝나는 위치를 명확하게 설명합니다. 찾는 것보다 균형 잡힌 따옴표를 찾는 것이 더 쉽습니다. <esc>
또는 모드를 종료하기 위해 무엇이든. 다시, 이것은 개인적인 취향과 습관입니다. :-)
:9,11g/^/move 8
... 마지막 숫자는 범위 -1의 시작이어야합니다 (Ingo의 대답에서 적응).
이 one-liner ( ~/.vimrc
)는 :Reverse
명령을 정의합니다 . :global
부품을 직접 사용할 수도 있지만 :move
(범위 시작 전에 줄을 반복적으로 이동시켜 반전시키는) 구문은 기억하기 쉽지 않습니다.
:command! -bar -range=% Reverse <line1>,<line2>global/^/m<line1>-1
<line1>
& <line2>
는이 작업을 다양한 범위에서 수행해야합니다 :7,9Reverse
( 예 :의 기능은 또는 command
아닙니다 ). 더 간단한 것도 작동하지만 전체 버퍼에만 적용됩니다.global
move
:command! -bar -range=% Reverse :global/^/m 0
순수한 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
자세한 내용은 확인 하십시오.
자세한 아이디어는 다음을 참조하십시오.
:g/^/m0
와 같은 :g/^/move 0
존의 대답 인?
tac
). 그러나 나는 downvote가 답이 반복되기 때문이라고 생각합니다.
기능성 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>)))
hlsearch
의 :g/
명령 과 같은 내용 ( 사용 가능한 경우 )을 강조 표시하지 않습니다 ...하지만 성능이 떨어질 수 있습니까? getline(1, line('$'))
메모리의 전체 버퍼를 가져 오기 때문 입니다. reverse()
제자리에있는 것처럼
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