Vim 정규식에서 '\ zs'와 '\ @ <='원자의 차이점은 무엇입니까?


11

이것은 문서에서 얻은 것입니다. \zs앞의 정규식과 \@<=일치시킨 후 "강조 표시된 부분을 시작합니다", 앞의 원자를 일치시킨 후 "강조 표시된 부분을 시작합니다" . 그러나 나는 이것의 미묘함을 정확하게 이해하지 못하므로 누구나 어떻게 조금 더 깊이 다른지 설명 할 수 있습니까?

이것이 내가 궁금해하는 이유입니다.

/\_s\zsnnoremap

즉,이 선택 nnoremap공백 또는 시동의 라인 앞에 (즉, 앞의 행의 개행, 따라서 \_이전의 s)을 실행 gn카메라 모드를 입력하기 위해 시각적으로 선택 어떤 이유로, 다음 일치 단지 첫 번째 열 (즉, 처음 n에이 nnoremap) 선택 - 전체 사실에도 불구 nnoremap단어가됩니다 강조 와 함께 :hlsearch켜져.

그러나 대신 검색을 실행하면

/\_s\@<=nnoremap

그런 다음 gn전체 nnoremap를 올바르게 선택하십시오. 여기서 무슨 일이 일어날 수 있습니까? 내가 모호한 버그를 발견 했습니까?


나는 그것의 생각 :h patterns하지만 내 기억은 정규식이 그 차이점을 설명하는 데 도움이된다면 원자로 구성되어 있다고 제안합니다.
D. Ben Knoble

답변:


15

이것은 실제로 모호한 버그를 발견 한 것 같습니다. gnVim 7.3에 대해 2012 년에 textobject를 다시 구현했습니다 . 기본적으로 다음과 같은 방식으로 작동합니다.

1) 현재 정규식의 마지막 일치 항목을 뒤로 검색합니다.

2) 현재 정규식의 다음 일치를 검색합니다.

커서가 이미 1의 시작에 있었더라도 다음 일치의 시작에 커서가 있음을 분명히해야합니다. 드디어

3) 현재 정규식의 끝을 검색합니다. 커서를 거기에 놓습니다.

이제 여기서 발생하는 것은 현재 경기의 끝에 대한 검색이 랩되고 이전 경기의 끝으로 돌아갑니다 ( wrapscan1에 대해 비활성화 된 후 이미 설정 되었기 때문 ). 그런 다음 Visual 마커를 시작 영역 (2 끝) 및 다음 검색 항목 3으로 이동 한 영역으로 설정합니다.

문제를 자세히 살펴보고 나중에 Vim 용 패치를 제출할 것입니다.

[업데이트 22.05.2018] 이 동작을 해결하기 위한 패치 를 작성하여 제출했습니다 .

[Update2 22.05.2018] 그리고 패치는 패치 레벨 8.1.0018 로 병합되었습니다.

[업데이트 22.10.2019] Vim 패치 8.1.629 부터 세 번째 단계는 더 이상 수행되지 않습니다. 대신 Vim은 이제 경기의 시작 부분을 찾을 때 경기의 끝을 결정할 수 있습니다 (2 단계).


8

기독교인은의 버기 행동에 관한 문제를 완전히 다루었 gn지만 여전히 \zs와 사이에는 근본적인 차이점이있다 \@<=. 가장 큰 것은 \@<=선행 원자를 수정하는 반면, \zs독립형 원자입니다.

치다:

Xnnoremap

\%1cX\zsnnoremap     (regex 1)
\%1cX\@<=nnoremap    (regex 2)
\%2cX\@<=nnoremap    (regex 3)

\%1c열 1과 일치하고 X가 있기 때문에 정규식 1이 일치 합니다. \zsX 다음의 위치에서 일치를 다시 시작하게합니다.

그러나 \%1c첫 번째 열과 일치 하지만 X\@<=너비가 0이고 (문서에서 언급 한 바와 같이) nnoremap열 2에서 시작 하기 때문에 정규식 2는 일치하지 않습니다 .

정규식 3 nnoremap은 열 2에서 시작한 이후 일치 합니다.


1
열 1과 2 사이의 위치 차이를 구성 할 것이 없기 때문에 정규식 2가 실패한다고 생각하지 않습니다. 문제가 있으면 nnoremap정규식에서 제거 하면 일치하는 결과가 나타납니다. 그러나 정규 표현식이 없으면 여전히 실패합니다. 나는 \%1cX\@<=존재할 수없는 위치를 표현 하기 때문에 실패한다고 생각 합니다. \%1c1 열의 위치를 ​​일치시키고 그 전에 X\@<=문자 X가 일치 하도록 요청 합니다. 그러나 첫 번째 열 앞에는 문자가있을 수 없습니다. 그렇기 때문에 X점 (모든 문자)으로 바꾸어도 정규식이 \%1c.\@<=계속 실패합니다.
user938271

4

\zs전체 정규식에 적용되고 다음 문자를 전체 일치의 첫 번째 문자로 설정합니다. 앞에 나오는 내용 \zs은 일치하는 텍스트의 일부로 포함되지 않습니다.

\@<=반면에, 주변 원자에만 직접 영향을 미치므로 다음 원자가 선행 원자 뒤에 오는 경우에만 일치하도록 지정할 수 있습니다. 예를 들어 정규 표현식은 다음과 같습니다.

\vbar.*(foo)@<=bar

두 개의 인스턴스 bar(인스턴스 자체 포함) 사이의 모든 텍스트를 일치 하지만 두 번째가 앞에 오는 경우에만 일치합니다 foo. 즉, 다음과 일치합니다.

barbazfoobar

하지만:

barbazbazbar

때문에 \@<=이 방법으로 지역화, 당신도 사용할 수있는 \@<=하나의 표현에서 여러 번 :

\vbar.*(foo)@<=bar.*(foo)@<=bar

다음은 세 개의 인스턴스 와 일치 bar하지만 두 번째가 각각 앞에 오는 경우에만 일치 합니다 foo.

즉 텍스트가 주어진 경우 :

barfoobarbazfoobar
barfoobarbazbazbar
barbazbarbazfoobar

첫 번째 줄만 일치합니다.


그러나 첫 번째 lookbehind를와 교환 할 수 있습니다 \zs. 즉, 다음과 같이 작동 \vfoo\zsbar.*(foo)@<=bar합니다.
Karl Yngve Lervåg

@ KarlYngveLervåg 좋은 지적입니다. 구별을 명확하게하고 \zs전혀 대체 할 수없는 예제를 사용하도록 편집했습니다 .
Rich

그래서, 내 이해, \zs그리고 \ze정규 표현식 패턴 주위 표정으로 교체 할 수 있습니다, 그들은 바로 더 강력한있어? 더 강력한 원인은 두 번 이상 사용할 수 있으며 그룹화 할 수 있습니다 \(\). 또한 그들은 정규 표현식을 둘러싼 펄의 모습처럼 작동하기 때문입니다. 실수가 있습니까?
klaus

1
@klaus 그것은 나에게 맞는 것 같습니다 (전문가는 아니지만). 하지만 둘러보기보다 빠르기 때문에 가능하면 \zs/ 를 사용해야합니다 \ze.
Rich

이해했다. 그리고 \zs그리고 \ze분명히 더 직관적이다. 설명 주셔서 감사합니다.
클라우스
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.