일치하는 패턴을 모든 줄에 결합하는 방법은 무엇입니까?


12

나는 특정 패턴 (예 :이 라인을 함께 라인에 가입 하시겠어요 ;사용하는 경우 그러나,) g/;/j번이라고 몇 않는 예상대로 작동하지 않습니다.

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

a
1;
2;
3;
4;
5;
b
6;
7;
8;
9;
c

사용시 : :g/;/j출력은 다음과 같습니다.

a
1; 2;
3; 4;
5; b
6; 7;
8; 9;
c

또는 :g/;/-j제공합니다 :

a 1; 2; 3; 4; 5;
b 6; 7; 8; 9;
c

와 비슷합니다 : :g/;\_.\{-};/j.

내 예상 출력은 다음과 같습니다

a 
1; 2; 3; 4; 5;
b
6; 7; 8; 9;
c

패턴이 포함 된 모든 선이 서로 연결됩니다.

이것이 어떻게 달성 될 수 있습니까?


3
FWIW :g/;/j는 두 단계로 이루어지기 때문에 작동하지 않습니다. 먼저 버퍼를 스캔 한 다음 명령을 일치하는 줄에 적용합니다.
romainl

답변:


12

문제에 대한 가능한 설명

:g/;/j작동하지 않는 이유 는 :g명령이 2 패스 알고리즘으로 작동 하기 때문입니다 .

  • 첫 번째 패스 동안 패턴을 포함하는 라인을 표시합니다. ;
  • 두 번째 패스 중에는 표시된 라인에서 작동합니다.

두 번째 패스 동안에, :g광고 결합 1;라인을 2;하기 때문에 1;첫 번째 패스 동안 표시되었다. 그러나 나는 (확실하지)가 참여하지 않는 것으로 의심 1; 2;3;라인이 있기 때문에 2;더 이상 존재하지 않는, 그 양은 라인과 합병되었습니다 1;이미 처리되었습니다.

따라서 :g첫 번째 패스 ( 3;) 중에 표시된 다음 행을 찾아 다음 행 ( )과 결합합니다 4;. 문제 반복, 그것은 가입 할 수 없습니다 그 이후 3; 4;5;라인이 있기 때문에 4;더 이상 존재하지 않습니다.

솔루션 1 (vimscript 포함)

어쩌면 포함하는 줄 ;이 발견 될 때마다 함수를 호출 하여 이전 줄에도 세미콜론이 있는지 확인할 수 있습니다.

function! JoinLines()
    if getline(line('.')-1) =~ ';'
        .-1join
    endif
endfunction

그런 다음 다음 전역 명령을 사용하십시오.

:g/;/call JoinLines()

또는 기능없이 :

:g/;/if getline(line('.')-1) =~ ';' | -j | endif

해결책 2 (vimscript없이)

:g/;/.,/^[^;]*$/-1j

전역 명령 :g이 패턴을 찾을 때마다 다음 명령 ;을 실행합니다. .,/^[^;]*$/-1j

다음과 같이 분류 할 수 있습니다.

:g/pattern/a,bj

어디 :

pattern = ;
a       = .           = number of current line
b       = /^[^;]*$/-1 = number of next line without any semicolon minus one

b 다음과 같이 더 나눌 수 있습니다.

/    = look for the number of the next line matching the following pattern
^    = a beginning of line
[^;] = then any character except a semicolon
 *   = the last character can be repeated 0 or more times
 $   = an end of line
 /   = end of pattern
 -1  = removes one to the number you just got

j:join다른 Ex 명령과 마찬가지로 범위가 앞에 올 수있는 Ex 명령 의 약식 입니다.
: 여기가 범위 앞에있어 .,/^[^;]*$/-1( a,b)
범위의 형식은 다음 과 일반적으로 2 개 라인의 숫자를, 당신이 줄 수 사이의 그룹에서 작동 할 수 있도록 하고 대신 하나. a,babab

따라서 j명령은 현재 행 ( a)과 세미콜론 빼기 ( b)를 포함하지 않는 다음 행 사이의 모든 행을 결합합니다 .

자세한 내용은 다음을 참조하십시오.

:help :global
:help :join
:help :range

2

나는 항상 글로벌 검색으로 비슷한 조인을하고 교체합니다.

s /; \ n /; /

\n 개행과 일치합니다.

빈 줄을 찾아 삭제하려면

s / ^ $ \ n //

왜 그런지 잘 모르겠지만 새 줄을 삽입하려면 사용해야합니다. \r


s혼자서 한 줄만 작동하여 전역으로 만들려면을 사용해야 %s하지만 ;
비줄을

2
@kenorb Ehm 아니요, :s원하는대로 정확하게 명령을 사용할 수 있다고 생각합니다 . 나는 이것이 %s/;\n\(.*;\)\@=/;/당신이 필요로하는 것이라고 생각 합니다.
Christian Brabandt
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.