줄 바꿈이 검색 레지스터 내에서 널 문자로 변환되고 명령 행에서 캐리지 리턴으로 변환되는 이유는 무엇입니까?


12

다음 텍스트가있는 경우 :

foo
bar

시각적으로 선택하여 복사합니다.
텍스트는 이제 명명되지 않은 레지스터에 저장되며 "그 내용은 다음과 같습니다 (출력 :reg ") :

""   foo^Jbar^J

차트 에 따르면 ^J, 줄 바꿈에 대한 캐럿 표기법 인 것 같습니다 .

다음과 같이 a입력 하여 이름이없는 레지스터를 레지스터에 복제하려면 :let @a = @"
다음과 같이 내용을 출력 :reg a하십시오.

"a   foo^Jbar^J

바뀌지 않았습니다.

을 입력하여 검색 레지스터에 복제하면 :let @/ = @"내용은 다음과 같습니다 (출력 :reg /).

"/   foo^@bar^@

이전 차트에 따르면 ^@Null 문자에 대한 캐럿 표기법 인 것 같습니다 .
왜 줄 바꿈이 검색 레지스터 내에서 자동으로 널 문자로 변환 a됩니까 (레지스터가 아님)?

이름을 지정하지 않은 레지스터를 명령 줄 (또는 이후의 검색 내부 /)에 :<C-R>"삽입 하면을 입력하여 다음을 삽입합니다.

:foo^Mbar^M

마지막 차트에 따르면 ^M, 캐리지 리턴에 대한 캐럿 표기법 인 것 같습니다.
명령 행에서 줄 바꿈이 캐리지 리턴으로 자동 변환되는 이유는 무엇입니까?

편집 :

일반적으로 다음을 입력하여 리터럴 제어 문자를 삽입 할 수 있습니다.
<C-V><C-{character in caret notation}>

예를 들어을 <C-R>입력하여 리터럴 을 삽입 할 수 있습니다 <C-V><C-R>.
겉으로 보이는 제어 캐릭터에 대해 할 수 있습니다.
그러나 버퍼를 입력하거나 명령 줄에 리터럴 LF를 삽입 할 수 없다는 것을 알았습니다. 입력하면 : 대신 null 문자를 <C-V><C-J>삽입 하기 때문 ^@입니다 ^J.
같은 이유로 LF가 검색 레지스터 내에서 NUL로 변환됩니까?

편집 2 :

에서는 :h key-notation, 우리는이를 읽을 수 있습니다 :

<Nul>       zero            CTRL-@    0 (stored as 10) <Nul>
<NL>        linefeed        CTRL-J   10 (used for <Nul>)

stored as 10첫 번째 줄에 및 일부 used for <Nul>두 번째 줄에는 LF와 NUL 사이의 중복 어떤 종류의가 있음을 나타낼 수 있습니다, 그들은 같은 일로 해석 될 수있다. 후 이전 명령을 실행하기 때문에 그러나이 같은 일이 될 수 없습니다 :let @/ = @"내가 입력하면, n2 개 라인의 다음 항목에 도착하는 일반 모드 foobar, 대신에 긍정적 인 일치를 받고, 나는 다음과 같은 오류 메시지가 :

E486: Pattern not found: foo^@bar^@

링크 외에도 NUL은 문자열의 끝을 나타내고 LF는 텍스트 파일의 줄 끝을 나타냅니다.

그리고 NUL이 stored as 10도움 말에 따르면 LF와 동일한 코드라면 Vim은 어떻게 2의 차이를 만들 수 있습니까?

편집 3 :

10도움말에서 알 수 있듯이 LF와 NUL은 동일한 십진 코드로 코딩됩니다 . 그리고 Vim은 컨텍스트 덕분에 2의 차이를 만듭니다. 10검색 및 명령 레지스터를 제외하고 10 진수 코드가 버퍼 또는 레지스터에 있는 문자를 만나면이 를 LF로 해석합니다.
그러나 검색 레지스터 ( :reg /) 에서 검색 컨텍스트에서 Vim end of line in a file은 문자열이 파일이 아니기 때문에 개념이 의미가없는 문자열 만 검색하기 때문에 NUL로 해석합니다. 여전히 \n검색 패턴으로 원자 를 사용 하지만 정규식 엔진의 기능 일뿐입니까?). 따라서 10가장 가까운 개념 ( end of stringend of line) 이므로 자동으로 NUL로 해석 됩니다 .

같은 방식으로 커맨드 라인 / 커맨드 레지스터 ( :reg :)에서 코드 10의 개념을 end of line in a file이해하지 못 하기 때문에 코드 를 CR로 해석합니다 . 가장 가까운 개념은 end of command빔의 해석 때문에 10타격이 있기 때문에하는 CR과 같은 Enter명령을 실행 / 종료로가는 길이며, CR은 타격과 동일 Enter할 때를있는 그대로 하나의 삽입 이후 <C-V><Enter>, ^M표시됩니다.

10컨텍스트에 따라 코드가 변경 되는 문자의 해석 일 수 있습니다 .

  • 버퍼의 줄 끝 ( ^J)
  • 검색에서 문자열의 끝 ( ^@)
  • 명령 행의 명령 끝 ( ^M)

2
때로는 예기치 않은 NULL 문자가 문자열을 처리하는 기본 C 함수로 인해 발생합니다. C가 링크 한 문자열처리하는 방법에 대한설명은 내부적으로 C가 문자열을로 구분한다는 것을 설명합니다 NULL. NULL이 목적을 위해 좋은 특성을 갖도록 텍스트에서 거의 발생하지 않습니다. 그 결과 C 프로그램 (vim)이 "빈"문자열을 내부 C 함수에 전달하려고하면
the_velour_fog

2
예를 들어 someFunction(arg1, "")arg 2는 "" "따옴표 사이에있는 항목으로 말 그대로"빈 "항목입니다. 문자열을 구분할 때 기본 C 구현에 의해"추가 "되었기 때문에 NULL이 나타날 수 있습니다. 당신이 이것을 확인하는 방법-그러나 가능한 원인으로 생각됩니다
the_velour_fog

1
의 토론 \r\n차이점:substitute 도 참조하십시오 .
jamessan

답변:


4

먼저,이 매우 포괄적이고 신중한 게시물에 감사드립니다.

몇 가지 테스트를 마친 후이 결론에 도달했습니다.

  1. 제어 문자는 캐럿 표기법을 사용하여 표시됩니다 : ^Mfor <CR>(캐리지 리턴) 및 ^Jfor <LF>(줄 바꿈). 버퍼에서 <EOL>(라인 끝)은 새 화면 행으로 표시되며 Enter 키를 사용하여 입력됩니다. <EOL>버퍼의 파일 형식에 따라 달라 <EOL> = <CR>|<LF>|<CR><LF>위해 mac|unix|dos각각.

  2. 버퍼를 편집 할 때는 파일 형식이 항상 설정됩니다. 열린 버퍼의 파일 형식을 변경하려면 다음 명령을 사용하여 변환하십시오 <EOL>.

    :set f[ile]f[ormat]=mac|unix|dos
    

    변환 이외에 <EOL>,이 명령은 변환 <LF><CR>에서 파일 포맷을 변경하는 경우 macunix|dos, 반대로, 및 <CR><LF>부터 파일 포맷을 변경하는 경우 unix|dosmac. 버퍼의 실제 바이트를 보려면 편리한 16 진 편집기 xxd를 사용하여 버퍼의 텍스트 표현을 16 진 표현으로 변환하는 다음 명령을 사용할 수 있습니다.

    :%!xxd
    
  3. (명령으로 보여 레지스터 :reg[isters]또는 :di[splay]), <EOL>항상 표시^J(하지만 전부는 아닙니다 ^J이다 <EOL>상관없이 버퍼의 파일 형식). 그러나 <EOL>되어 저장 그들이해야한다. 레지스터 에서 시각적으로 실제 ^J(즉 <LF>)를 다른 ^J(즉 ,) 구별 <EOL>할 수 있도록 다음과 같은 제어 문자의 캐럿 표기법 대신 16 진수 값을 표시하는 다음 명령을 사용할 수 있습니다 <EOL>.

    :set d[ispla]y=uhex
    
  4. 검색 패턴 및 대체 문자열에서 :

    \r = newline different from <EOL> (<CR> if <EOL> = <CR><LF>|<LF>, <LF> if <EOL> = <CR>)
    \n = <EOL>
    
  5. 어디에나:

    <C-V><C-M>|<C-V><EOL> = newline different from <EOL>
    <C-V><C-J> = <NUL>
    

    파일 형식이 경우이 쇼 것으로 dos, 그것은 입력 불가능 <LF>하기 때문에, <EOL> = <CR><LF>하고 <C-V><C-M>|<C-V><EOL> = <CR>.

  6. 대체 문자열에서 :

    • 와 다른 개행 <EOL>은 다음 과 같이 해석 됩니다 <EOL>.

    • <EOL>해석 됩니다 <NUL>.

    그래서, (4)에 따라, :%s[ubstitute]/\r/\r/g에서 모든 줄 바꿈 다른 대체 <EOL>와 버퍼 <EOL>, 동안 :%s[ubstitute]/\n/\n/g을 대체 매 <EOL>와 버퍼 <NUL>.

  7. 검색 레지스터 /및 명령 레지스터 :에서 <EOL>변환 됩니다.

    • 또는 각각 <EOL>의 레지스터에서 삽입 될 때 와 다른 개행 ;/<C-R>{register}:<C-R>{register}

    • <NUL>:let @/=@{register}또는 :let @:=@{register}각각을 레지스터에서 삽입 할 때 .

  8. 버퍼에서를 사용하여 레지스터에서 삽입 할 때 와 다른 개행 <EOL>변환 됩니다 .<EOL>i<C-R>{register}

줄 바꿈이 검색 레지스터 내에서 널 문자로 변환되고 명령 행에서 캐리지 리턴으로 변환되는 이유는 무엇입니까?

<LF>명명되지 않은 레지스터 "에서 다른 레지스터로 복사하기 전에 레지스터 에 입력 <LF>하고 넣어야합니다 ". 파일 형식이 unix이면 yy빈 줄 을 사용하여 수행 할 수 있습니다 . 파일 형식이 mac이면 i<C-V><C-M><Esc>yl; 파일 형식이 dos인 경우 입력 할 수 없습니다 <LF>(참조, 5).

이제 당신의 진술은 부분적으로 잘못되었습니다.

  • <LF>레지스터 "에서 검색 레지스터 /및 명령 레지스터 로 복사하는 데 동일한 방법을 사용하지 않습니다 :. 당신이 사용하는 :let @/=@"레지스터로 복사하는 /:<C-R>"레지스터에 복사하는 :. 사용 /<C-R>"하고 :<C-R>"각각 당신에게 동일한 결과를 (줄 것이다 <CR>) 두 경우 모두;

  • <LF>두 가지 다른 복사 방법으로 변환하는 것은 파일 형식이 unix. 이 경우 mac, <LF>되어 있지 레지스터에 복사 할 때 변환 /또는 레지스터 :,하고 있는지 dos당신도 입력 할 수 없습니다 <LF>.

올바른 진술은 7에 의해 주어진다. 그러나 나는 그 뒤에 이유를 정말로 모른다.


왜 이것이 이해하기 어려운가 ... 나는 SO와 vim-SE와 vim 도움말에 대한 여러 게시물을 조사했지만 완전히 일관성이 없으며 혼란 스럽습니다.
Violapterin의
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.