sコマンドで\ rと\ nが異なることを意味する理由は何ですか?


13

私たちは皆、検索時\nは改行であり、\r復帰(^M)であることを知っていますが、置換するとき\rは改行\nで、nullバイト(^@)です。

この非対称性の起源は何ですか?この振る舞いは...控えめに言っても独特です(そして最初に間違えたときはかなり非生産的です)奇妙な歴史的理由があると思います。

(偶然にも、この動作を「修正」してより直感的なものにする方法はありますか?)

回答:


10

最も基本的なレベルで:substituteは、前者は正規表現であり、後者は特定の追加のエスケープシーケンスを含むテキストであるため、検索と置換部分の間にすでに非対称性があります。これは、何を\n意味するかについての直感によって強調されています。

たとえば\n、検索でリテラルと一致しないことを考慮してください\n。それがあってもよいライン(EOL)バイトシーケンスの終わりと一致する\r\r\nまたはわずか\nに応じて'fileformat'緩衝液。

なぜ\r「EOLを挿入する」という意味で使用されているかについては、その背後にいくつかの歴史があります。Viには、ファイル内のNULバイトを処理する方法がありませんでした。Vimは、内部的にNULバイトをNLバイトに置き換えることにより、それを改善しました(C文字列はNULで区切られているため)。

この実装の詳細は、NULバイトを示すために使用されるその行の内部表現に単純に置換が挿入される:substituteため、動作に漏れ\nます。 \rEOLを挿入し、内部行を2つに分割します。Vimは実際にはメモリにEOLバイトを保存せず、代わりにバッファの読み取り/書き込み時にそれらを(デ)シリアル化します。

現在、多くのユーザーの多くのスクリプトと筋肉の記憶を壊さずに変更することはできません。ありがたいことに、それはに文書化されてい:help sub-replace-specialます。


6

NULバイトはCでの文字列の終端であり、この理由のためにVimはのマニュアルに記載、この規則を使用しています:h NL-used-for-Nul

ファイル内の<Nul>文字は、メモリ内に<NL>として保存されます。ディスプレイでは、「^ @」として表示されます。翻訳は、ファイルの読み取りおよび書き込み時に行われます。<Nul>を検索パターンと一致させるには、CTRL- @または「CTRL-V 000」を入力するだけです。これはおそらくあなたが期待することです。内部的には、検索パターンで文字が<NL>に置き換えられます。珍しいのは、CTRL-V CTRL-Jを入力しても<NL>が挿入されるため、ファイル内で<Nul>も検索されることです。{Viはファイル内の<Nul>文字をまったく処理できません}

この規則は:s/.../.../コマンドに波及しましたが、substitute()関数には波及しませんでした。 \rそして、\nで置換文字列にsubstitute()呼び出し元の意味を保ちます。

どちらの振る舞いにも、より深い理由はないと思います。Vimは単にオリジナルから有機的に進化しましたvi。大きな青写真はありませんでした。機能を整理するための比較的少ない労力で、機能が互いの上に積み上げられました。


0

他のViクローンは、置換をサポートしていない(\rまたは\n実際のバックスラッシュと文字として)が、行を2行に分割するという実際の^MCTRL-V Enter)意味の動作標準の動作です。

replで <carriage-return>を入力すると(exモードではエスケープ<backslash>が、openまたはviモードではエスケープ<control> -Vが必要)、その時点で行が分割され、編集バッファーに新しい行が作成されます。 。<carriage-return>は破棄されます。

Unix Historyアーカイブでは、BSD ex / viの最初のバージョンは4.1cBSD(@(#)ex_re.c 7.2 10/16/81であり、4BSD(@(#)ex_re.c 6.2 10/23/80)には存在しません[4.1aおよび4.1bはアーカイブに存在しません]。

関連するコードは次のとおりです。

/* ^V <return> from vi to split lines */
if (c == '\r')
    c = '\n';

これは、ニュースファイルにも記載されています

rhsで^ V <return>を使用することにより、viからの代替コマンドで行を分割できるようになりました。これにより、exコマンドモードを使用する最後の正当な理由が考慮されます。

exコマンドモードで以前にサポートされていた動作は、バックスラッシュ入力(バックスラッシュと実際の改行)で改行を挿入することでした。


0

非対称性の起源は、コンピューティングの歴史にまで遡ります。

短縮版:

<CR> & <LF>  (Carriage-Return and Linefeed) 
== 
\r & \n

長いバージョン:
最初の画面は基本的にテレタイプ(TTY)のデジタルバージョンであり、制御コードを使用してプリンターと同様の動作を生成しました。キャリッジリターンでカーソル(またはプリントヘッド)が開始列に移動しました。改行は(画面上の)次の行に進み、用紙を1行先に送りました。

プリンターの場合、ペアリングを行う必要<CR><LF>があります。そうしないと、出力が正しく表示されません。初期の画面では、この問題は依然として真実でした。

DOS(およびsorta-Windows以降)は古い標準に従い、でテキストを保存します<CRLF>

* NIXテキスト(ほとんどのviユーザーはおなじみです)は<LF>、効率のためにのみ使用されます。

Windowsでテストするには、ワード/ワードパッドを使用し、「as type:Text-MS-DOS format」というテキストを数行保存します。次に、その同じファイルをメモ帳で開きます。正常に見えるはずです。次に、同じファイルを「タイプ:テキスト」としてワード/ワードパッドに保存します。メモ帳はすべての改行を無視し、行をまとめて実行します。[メモ帳のテキスト形式はデフォルトで\r\n組み合わせになり、ワード/ワードパッドはデフォルトで\n。]になります。

\ rは次と同等のコードです <CR>

\ nは次と同等のコードです <LF>

そして、viでの(非常に限られた)経験で<CRLF>は、DOSテキストエディターからの組み合わせを「修正」しようとします。viは1文字を削除し、に置き換えました<NUL>。viの使用をやめた理由の大部分。


2
すべてのあなたの情報が面白いですが、なぜ、それだけで伝え\rている<CR>\nあります<LF>。これは、なぜ、実際の問題に対処しない\n\r振る舞いは異なる別の状況では。
タンブラー41

ありがとうございました!:-)あなたが答えたとき、私はそれを変えていました。(最後の段落を追加。)
ロビン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.