なぜラインフィードが検索レジスタ内でヌル文字に変換され、コマンドラインでキャリッジリターンに変換されるのですか?


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を挿入することができないんだということに気付きました:<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>2行目は、LFとNULとの間の重なりのいくつかの並べ替えがあることを示している可能性があり、そして、彼らは同じものとして解釈される可能性があること。前のコマンドを実行した後ので、しかし、彼らは、同じことをすることはできません:let @/ = @"I型の場合、n通常モードでは、2行の次の発生を取得するfoobar、代わりに正の一致を得るための、私は次のエラーメッセージがあります。

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

このリンクのほかに、NULは文字列の終わりを示し、LFはテキストファイルの行の終わりを示すと説明しているようです。

そして、NULがstored as 10ヘルプにあるように、LFと同じコードである場合、Vimはどのように2の違いを作ることができますか?

編集3

10ヘルプにあるように、LFとNULは同じ10進コードでコーディングされているかもしれません。また、Vimはコンテキストのおかげで2つの違いをもたらします。10検索およびコマンドレジスタを除き、10進コードがバッファまたはレジスタにある文字と一致する場合、LFと解釈します。
しかし、検索:reg /のコンテキストではend of line in a file、文字列がファイルではないためにVimは概念が意味をなさない文字列のみを検索するため、検索レジスタ()ではNULとして解釈します(それでも\n検索パターンでアトムを使用しますが、それはおそらく正規表現エンジンの機能ですか?)したがって10、最も近い概念(end of stringend of line)であるため、自動的にNULとして解釈されます。

同様に、コマンドライン/コマンドレジスタ(:reg :)では、コード10をCRとして解釈しますend of line in a file。ここでの概念は意味をなさないためです。最寄りのコンセプトはend of commandVimの解釈ので10打撃があるため、CRなどEnterのコマンドを実行/エンドへの道であるとCRを押すと同じであるEnterときを持つリテラル1のインサート以来、<C-V><Enter>^M表示されています。

10コンテキストに応じてコードが変更される文字の解釈かもしれません:

  • バッファ内の行末(^J
  • 検索の文字列の終わり(^@
  • コマンドラインのコマンドの終わり(^M

2
時には、予期しないNULL 文字の発生は、文字列を処理しているC関数によって引き起こされます。Cがリンク先の文字列処理する方法に関するこの説明では、内部的にCがNULLNULLsがテキスト内でめったに出現しないため、この目的に適した文字になります。この結果、Cプログラム(vim)が内部C関数に「空の」文字列を渡そうとした場合、
the_velour_fog

2
例えばsomeFunction(arg1, "")、arg 2が"" 「引用符の間の項目で、文字通り何もない-「空」。NULLが表示される場合があります。これを確認する方法-しかし、考えられる原因として
頭に浮かぶ-the_velour_fog

1
の議論\r\n違い:substituteも参照してください。
ジェームスサン

回答:


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>してregisterに入れる必要があります"。ファイル形式がの場合、空の行で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ヘルプに関するいくつかの投稿を調べましたが、完全に一貫しているわけではなく、まだ混乱しています。
ビオラプテリン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.