これは少しの知識を記録するための記事で、この知識はとても小さいです。しかし、実際には面白いと思っていて、私が扱えるものであり、明確に説明できるものです。
行の定義について#
事の発端は、以下のようなリマインダーから来ています。git diff
を見たことがあると思います。\No newline at end of file
diff --git a/demo.py b/demo.py
index 8cde782..e75154b 100644
--- a/demo.py
+++ b/demo.py
@@ -1 +1 @@
-print("hello world")
+print("hello world")
\ No newline at end of file
一つの疑問を考えさせてください。なぜ 1 行減ったのではなく、元の最後の行が変更されたのか。なぜ print("hello world")\n
と print("hello world")
を区別する必要があるのか。
これは実際に posix における行の定義に関係しています。(3.206 Line)
0 個以上の非
<newline>
文字の列と、終端の<newline>
文字。
行は、0 個以上の非 <newline>
文字の系列と、そして終端の <newline>
文字で構成されています。ここでの「そして」という言葉に注意してください。これは posix の定義において、行は必ず <newline>
で終わる必要があることを意味します。したがって正確には、改行文字は終了する行の一部であり、改行文字のない行は行とは見なされません。
したがって、上記の操作では元の完全な行の中の \n
を削除しました。
可能性のある問題#
ですので、posix 標準に従ったコマンドやソフトウェアは、行の終了が \n
であることを保証します。ファイルの末尾が改行文字でない場合、いくつかの状況で問題が発生する可能性があります。
ここでは一例として wc -l
を挙げます:
私の解決策#
- vim や nono のようなツールは、ファイルを保存する際に自動的に末尾に空行を追加します。
- vscode プラグイン:ファイルを保存する際に、最後の改行文字を自動的に保証します。
- linter プラグイン:pylint などの linter プラグインをインストールし、改行文字がない場合に自動的に改行文字を追加します。
- シェルスクリプト:ディレクトリ内のすべてのファイルに対して、改行文字がない場合は自動的に改行文字を追加します。
nini_ensure_newline(){ find . -type f | while read -r file; do if [ "$(tail -c 1 "$file")" != '' ]; then echo "Processing $file" echo "" >> "$file" fi done }
参考資料#
- linux - プログラムソースファイルの末尾に空行が必要な理由 - SegmentFault 思否
実際、このリンクの回答は核心である posix 標準を認識しておらず、この問題はソフトウェアの新旧に関係ありません。新しいソフトウェアも posix 標準をサポートできますが、改行文字を行の終わりとして扱う必要があります。 - How to force newline at end of files and why you should do it | by Alexey Inkin | Medium
非常に詳細に説明されており、私のシェルコードの結末の説明も含まれています。 - missing-final-newline / C0304 - Pylint 3.0.0a8-dev0 documentation
Pylint にも対応するチェック項目があります。