viはファイルの末尾に改行文字(LF)を自動的に追加しますか?

viはファイルの末尾に改行文字(LF)を自動的に追加しますか?

私が理解できない奇妙な動作があります。 viは改行文字(ASCII:LF、Unix(AIX)システム)を特に入力しない場合は、ファイルの末尾に追加します。

viでファイルを編集します(最後に改行文字を入れないように注意してください)。

# vi foo   ## Which I will finish on the char "9" and not input a last newline, then `:wq`
123456789
123456789
123456789
123456789
~
~
  ## When I save, the cursor is just above the last "9", and no newline was added.

私はviがそれを「現状のまま」保存したいので、39バイト:それぞれ10個のASCII文字で構成される最初の3行(数字1〜9、その後に改行文字(私のシステムではLF)が来る)、そして最後の9文字行(改行/ LFを終了せずに文字1〜9)。

しかし、保存するとこんな感じです。40バイト(39の代わりに)とod は LF の終了を示します。:

# wc foo
       4       4      40 foo  ## I expected 39 here! as I didn't add the last newline
# od -a toto
0000000    1   2   3   4   5   6   7   8   9  lf   1   2   3   4   5   6
0000020    7   8   9  lf   1   2   3   4   5   6   7   8   9  lf   1   2
0000040    3   4   5   6   7   8   9  lf
0000050
     ## An "lf" terminates the file?? Did vi add it silently?

viと同じように、printfを使用してファイルを生成すると、期待どおりに動作します。

# ## I create a file with NO newline at the end:
# printf "123456789\n123456789\n123456789\n123456789" > foo2
# wc foo2  ## This one is as expected: 39 bytes, exactly as I was trying to do above with vi.
       3       4      39 foo  ## As expected, as I didn't add the last newline

  ## Note that for wc, there are only three lines!
  ## (So wc -l doesn't count lines; it counts the [newline] chars... Which is rather odd.)

# root@SPU0WMY1:~  ## od -a foo2
0000000    1   2   3   4   5   6   7   8   9  lf   1   2   3   4   5   6
0000020    7   8   9  lf   1   2   3   4   5   6   7   8   9  lf   1   2
0000040    3   4   5   6   7   8   9
0000047                                ## As expected, no added LF.

viを使用して2つのファイル(foo(40文字)とfoo2(39文字))を再度開くと、まったく同じように見えます。

viでfoo2を開くと(39文字、改行なし):wq編集せずにやってみてください、40文字を書いて改行が発生したと出ています!

更新されたviにアクセスできません(AIXでこれを実行しています。vi(いいえ)ウィム)バージョン3.10のようですが? (「-version」やそれを知る他の方法はありません))。

# strings /usr/bin/vi | grep -i 'version.*[0-9]'
@(#) Version 3.10

vi(最新バージョンにはありませんか、それともVim?)がファイルの末尾に自動的に改行文字を追加するのが正常ですか? (私の考えでは、〜は前の行が改行文字で終わっていないことを示します。)

-

編集する:次の回答のおかげで、いくつかの追加アップデートといくつかの要約が提供されます。

  • viは、改行のないファイルを作成すると(ファイルが空でない場合)、自動的に末尾の改行を追加します。

  • 書き込み中にのみこれが行われます! (つまり、:wを使用するまで:eを使用して、ファイルが開かれたときと同じであることを確認できます。保存すると、特定の警告なしに新しい行が自動的に追加されます。ある方法を見つけるのに役立ちました。)

  • これは(自動修正)POSIXアクション! (@barefoot-ioの回答を参照)

ベストアンサー1

POSIXではこの動作が必要なので、特別な点はありません。

~からPOSIX vi マニュアル:

入力ファイル

vi コマンドでサポートされている入力ファイルの説明については、ex コマンドの入力ファイルのセクションを参照してください。

道を進むと到着POSIX プリマニュアル:

入力ファイル

入力ファイルはテキストファイルまたはテキストファイルになるファイルでなければなりません。ただし、不完全な最後の行は{LINE_MAX} - 1バイトより長くなく、NUL文字を含みません。デフォルトでは、不完全な最後の行は後ろに<newline>があるものとして扱われるべきです。 ex実装では、オプションで他の形式のファイルを編集することもできます。

vi マニュアルの出力ファイルセクションも次にリダイレクトされます。

結果ファイル

exの出力はテキストファイルでなければなりません。

POSIX定義ペア:

3.397 テキストファイル

ゼロ行以上の文字を含むファイル。この行には NUL 文字は含まれず、<newline> 文字を含めて {LINE_MAX} バイトより長くすることはできません。 POSIX.1-2008はテキストファイルとバイナリファイルを区別しませんが(ISO C標準を参照)、多くのユーティリティはテキストファイルを操作するときに予測可能または意味のある出力のみを生成します。これらの制限を持つ標準ユーティリティは、常にSTDINまたはINPUT FILESセクションに「テキストファイル」を指定します。

3.206ライン

ゼロ個以上の<newline>以外の文字と終了<newline>文字のシーケンス。

これらのマニュアルページの抜粋の文脈では、これらの定義は適切なex / vi実装が間違った形式のテキストファイルを許可する必要がありますが、ファイルの唯一の欠陥が最後の改行文字がない場合は、ファイルのバッファに書き込むときの結果は次のようになります。を意味します。有効なテキストファイルでなければなりません。

この記事はPOSIX標準2013バージョンを参照していますが、関連条項は1997年以前のバージョンでも登場しました。

最後に、exの改行文字が人気がないことがわかったら、UNIX 7版(1979)に対する不慣れのために深刻に侵害されたと感じるでしょう。マニュアルから:

ファイルを読み取ると、edはASCII NUL文字と最後の改行文字の後のすべての文字を削除します。 ASCII以外の文字を含むファイルの読み取りを拒否します。

おすすめ記事