私はここの誰もがすべてのテキストファイルが改行で終わるべきであるという格言に精通していると思います。私は長年この「ルール」について知っていましたが、いつも疑問に思っていました。なぜですか?
私はここの誰もがすべてのテキストファイルが改行で終わるべきであるという格言に精通していると思います。私は長年この「ルール」について知っていましたが、いつも疑問に思っていました。なぜですか?
回答:
それは、POSIX標準が行を定義する方法だからです。
- 3.206ライン
- ゼロ個以上の非<改行>文字と終端の<改行>文字のシーケンス。
したがって、改行文字で終わっていない行は、実際の行とは見なされません。そのため、一部のプログラムでは、ファイルの最後の行が改行で終了していない場合、ファイルの最後の行の処理に問題があります。
ターミナルエミュレータで作業する場合、このガイドラインには少なくとも1つの大きな利点があります。すべてのUnixツールはこの規則を想定しており、これを使用します。たとえば、ファイルをcat
で連結する場合、改行で終了したファイルは、次のファイルがない場合とは効果が異なります。
$ more a.txt
foo
$ more b.txt
bar$ more c.txt
baz
$ cat {a,b,c}.txt
foo
barbaz
また、前の例でも示されているように、コマンドラインでファイルを表示すると(例:を介してmore
)、改行で終了するファイルは正しい表示になります。不適切に終了したファイルは文字化けすることがあります(2行目)。
一貫性を保つために、このルールに従うことは非常に役立ちます。そうしないと、デフォルトのUnixツールを処理するときに余分な作業が発生します。
別の方法で考えてみてください。行が改行で終了していない場合、コマンドをcat
便利にするなどの作業ははるかに困難です。次のようなファイルを連結するコマンドを作成するには
b.txt
し、c.txt
?もちろんこれは解けるが、あなたはの使用にする必要があるcat
(例えば、位置コマンドライン引数を追加することによって、より複雑にcat a.txt --no-newline b.txt c.txt
)、そして今のコマンドではなく、それは他のファイルと一緒に貼り付けられているか、個々のファイルを制御します。これはほぼ確実に便利ではありません。
…または、終了するのではなく継続することになっている行をマークするために、特殊な歩哨文字を導入する必要があります。さて、反転(行の終了文字ではなく行の継続)を除いて、POSIXと同じ状況に陥っています。
さて、POSIXに準拠していないシステム(現在は主にWindowsが主流です)では、要点は意味がありません。ファイルは通常改行で終わっておらず、行の(非公式)定義は、たとえば「改行で区切られたテキスト」である可能性があります。 (強調に注意してください)。これは完全に有効です。ただし、構造化データ(プログラミングコードなど)の場合は、解析が最小限で複雑になります。これは、通常、パーサーを書き換える必要があることを意味します。パーサーが元々POSIX定義を念頭に置いて作成されていた場合、パーサーよりもトークンストリームを変更する方が簡単です。つまり、「人工改行」トークンを入力の最後に追加します。
cat
、便利で一貫しているような方法でツールを作成することをはるかに難しくします。
各行は、最後の行を含め、改行文字で終了する必要があります。一部のプログラムでは、改行で終了していない場合、ファイルの最終行の処理に問題があります。
GCCは、それがあるため、それについて警告していないことができないファイルを処理し、それがために持っている規格の一部として。
C言語標準では、空ではないソースファイルは改行文字で終了する必要があり、その直前にバックスラッシュ文字を付けてはなりません。
これは「shall」句であるため、このルールの違反に対して診断メッセージを発行する必要があります。
これは、ANSI C 1989標準のセクション2.1.1.2にあります。ISO C 1999規格のセクション5.1.1.2(およびおそらくISO C 1990規格も)。
wc -l
は、改行で終了していない場合、ファイルの最終行をカウントしません。また、cat
最初のファイルの最後の行が改行で終了していない場合は、ファイルの最後の行と次のファイルの最初の行を1つに結合します。区切り文字として改行を探しているほとんどすべてのプログラムは、これを台無しにする可能性があります。
wc
はすでに言及されていることを意味します...
cat
およびのようなスレッドですでに大量に言及されているもの以外wc
)?
この回答は、意見ではなく技術的な回答の試みです。
POSIX純粋主義者になりたい場合は、次のように行を定義します。
ゼロ個以上の非<改行>文字と終端の<改行>文字のシーケンス。
出典:https : //pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_206
次のような不完全な行:
ファイルの終わりにある1つ以上の非<改行>文字のシーケンス。
出典:https : //pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_195
次のようなテキストファイル:
ゼロ以上の行に編成された文字を含むファイル。行にはNUL文字が含まれておらず、<newline>文字を含めて、長さが{LINE_MAX}バイトを超えることはできません。POSIX.1-2008はテキストファイルとバイナリファイルを区別しませんが(ISO C標準を参照)、多くのユーティリティはテキストファイルを操作するときに予測可能な、または意味のある出力のみを生成します。このような制限がある標準ユーティリティは、STDINまたはINPUT FILESセクションで常に「テキストファイル」を指定します。
ソース:https : //pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_397
次の文字列:
最初のヌルバイトで終了し、最初のヌルバイトを含む連続したバイトシーケンス。
出典:https : //pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_396
このことから、何らかのタイプの問題が発生する可能性があるのは、ファイルの行またはファイルをテキストファイルとして扱う場合(テキストファイルはゼロの組織であるため)以上の行、および<newline>で終了する必要があることがわかっている行)。
適例:wc -l filename
。
以下からwc
のマニュアル我々は読んで:
行は、<newline>文字で区切られた文字列として定義されます。
JavaScript、HTML、CSSファイルがテキスト ファイルであるという意味は何ですか?
ブラウザ、最新のIDE、およびその他のフロントエンドアプリケーションでは、EOFでEOLをスキップしても問題はありません。アプリケーションはファイルを適切に解析します。すべてのオペレーティングシステムがPOSIX標準に準拠している必要はないため、OS以外のツール(ブラウザなど)がPOSIX標準(またはOSレベルの標準)に従ってファイルを処理することは現実的ではありません。
その結果、UNIX OSで実行されているかどうかにかかわらず、EOFでのEOLがアプリケーションレベルで実質的に悪影響を及ぼさないことを比較的確信できます。
この時点で、クライアント側でJS、HTML、CSSを処理する場合、EOFでEOLをスキップしても安全であると自信を持って言えます。実際、<newline>を含まないこれらのファイルのいずれかを縮小することは安全であると言えます。
これをさらに一歩進めて、NodeJSに関する限り、非POSIX準拠の環境で実行できるという点で、POSIX標準に準拠することはできません。
それでは何が残っているのですか?システムレベルのツール。
つまり、発生する可能性のある唯一の問題は、POSIXのセマンティクス(たとえば、に示すような線の定義)に機能を準拠させるためのツールを使用することwc
です。
それでも、すべてのシェルが自動的にPOSIXに準拠するわけではありません。たとえば、bashはデフォルトでPOSIX動作になりません。それを有効にするスイッチがあります:POSIXLY_CORRECT
。
EOLが<newline>であることの価値について考えるための情報:https : //www.rfc-editor.org/old/EOLstory.txt
すべての実用的な目的と目的のために、ツールトラックにとどまり、これを検討しましょう。
EOLのないファイルを操作してみましょう。これを書いている時点で、この例のファイルはEOLのない縮小JavaScriptです。
curl http://cdnjs.cloudflare.com/ajax/libs/AniJS/0.5.0/anijs-min.js -o x.js
curl http://cdnjs.cloudflare.com/ajax/libs/AniJS/0.5.0/anijs-min.js -o y.js
$ cat x.js y.js > z.js
-rw-r--r-- 1 milanadamovsky 7905 Aug 14 23:17 x.js
-rw-r--r-- 1 milanadamovsky 7905 Aug 14 23:17 y.js
-rw-r--r-- 1 milanadamovsky 15810 Aug 14 23:18 z.js
注意してくださいcat
ファイルのサイズが正確にその個々の部品の合計です。JavaScriptファイルの連結がJSファイルの問題である場合、より適切な問題は、各JavaScriptファイルをセミコロンで始めることです。
他の誰かがこのスレッドで述べたようにcat
、出力が2行ではなく1行になる2つのファイルが必要な場合はどうでしょうか。つまり、cat
本来あるべきことを実行します。
man
のcat
だけはEOFへの入力まで、ない<改行>を読んで言及しています。の-n
切り替えはcat
、<newline>で終了していない行(または不完全な行)も行として出力することに注意してください。つまり、カウントは1から始まります(man
。
-n出力行に1から始まる番号を付けます。
POSIXがどのように線を定義するかを理解したので、この動作はあいまいになり、実際には非準拠になります。
特定のツールの目的とコンプライアンスを理解することは、EOLでファイルを終了することがどれほど重要かを判断するのに役立ちます。C、C ++、Java(JAR)などでは、いくつかの標準が改行の有効性を要求します-JS、HTML、CSSにはそのような標準はありません。
たとえば、代わりに使用してのwc -l filename
1が行うことができawk '{x++}END{ print x}' filename
、およびタスクの成功は、我々は我々が(例えばAなど縮小さJS我々は、サードパーティのライブラリを書いていないことを処理することがあり、ファイルによって危険にさらされていないので安心curl
私達のない限り- D)意図は、POSIX準拠の意味で行を数えることでした。
結論
JS、HTML、CSSなどの特定のテキストファイルのEOFでEOLをスキップしても、悪影響があるとしても、実際の使用例はほとんどありません。<newline>の存在に依存している場合、ツールの信頼性は、サードパーティのファイルによって発生する可能性のあるエラーまで、作成して開いたファイルにのみ制限されます。
話の教訓:EOFでEOLに依存する弱点を持たないエンジニアツール。
EOLのスキップがどのように悪影響を与えるかを調べることができるJS、HTML、CSSに適用されるユースケースを自由に投稿してください。
次の違いに関連している可能性があります:
各行が行末で終了する場合、これにより、たとえば、2つのテキストファイルを連結して、最初の実行の最後の行が2番目の行の最初の行になることが回避されます。
さらに、エディターは、ファイルが行末で終了するかどうかをロード時にチェックし、ローカルオプション 'eol'に保存して、ファイルの書き込み時にそれを使用できます。
数年前(2005年)には、多くの編集者(ZDE、Eclipse、Sciteなど)がその最終的なEOLを「忘れた」ため、あまり評価されませんでした。
それだけでなく、彼らは最終的なEOLを「新しい行を開始する」と誤って解釈し、実際にはすでに存在するかのように別の行を表示し始めました。
これは、上記のいずれかのエディターで開く場合と比較して、vimのような適切に動作するテキストエディターを備えた「適切な」テキストファイルで非常に目立ちました。ファイルの実際の最後の行の下に追加の行が表示されました。次のようなものが表示されます。
1 first line
2 middle line
3 last line
4
一部のツールはこれを期待しています。たとえば、wc
これを期待します:
$ echo -n "Line not ending in a new line" | wc -l
0
$ echo "Line ending with a new line" | wc -l
1
wc
いないと言えるかもしれません。
wc -l
印刷することです1
が、一部の人々は2番目のケースを印刷する必要があると言います2
。
\n
POSIX / UNIXのように、行の区切り文字ではなく、行の終止符と考えると、2番目のケースが2を出力すると予想するのはまったくおかしいです。
基本的に、最終的なEOL EOFを取得しないとファイルを正しく処理しないプログラムが多数あります。
これはC標準の一部として想定されているため、GCCはこれについて警告します。(5.1.1.2節)
これは、単純な端末が使用されたごく初期の時代に由来しています。改行文字は、転送されたデータの「フラッシュ」をトリガーするために使用されました。
今日、改行文字は不要になりました。もちろん、改行がない場合でも多くのアプリで問題が発生しますが、これらのアプリにはバグがあると思います。
ただし、改行が必要なテキストファイル形式の場合は、単純なデータ検証が非常に安価に行われます。ファイルの最後に改行がない行で終了すると、ファイルが壊れていることがわかります。各行に1バイト追加するだけで、CPU時間をほとんど必要とせずに、壊れたファイルを高精度で検出できます。
別の使用例:テキストファイルがバージョン管理されている場合(この場合、特にgitの下にありますが、他にも適用されます)。コンテンツがファイルの最後に追加された場合、以前は最後の行であった行が編集されて、改行文字が含まれます。つまり、blame
その行が最後に編集されたのはいつかをファイルで確認すると、実際に確認したい前のコミットではなく、テキストの追加が表示されます。
\n
)。問題が解決しました。
上記の実用的な理由に加えて、Unixの創始者(Thompson、Ritchieなど)またはその前のMulticsが、行セパレーターではなく行ターミネーターを使用する理論的な理由があることに気づいたとしても、驚くことではありません。ターミネーターは、行のすべての可能なファイルをエンコードできます。行区切り記号を使用すると、ゼロ行のファイルと単一の空行を含むファイルの間に違いはありません。どちらもゼロ文字を含むファイルとしてエンコードされます。
その理由は次のとおりです。
wc -l
、改行で終わっていない場合、最終的な「行」はカウントされません。cat
だけで問題はありません。解釈する必要なく、各ファイルのバイトをコピーするだけです。に相当するDOSはないと思いますcat
。を使用copy a+b c
すると、ファイルの最後の行がファイルa
の最初の行とマージされますb
。おそらく単純に、一部の構文解析コードが存在することを期待していたと考えられます。
私がそれを「ルール」と考えるかどうかは確かではありませんし、それは確かに私が信心深く守るものではありません。ほとんどの賢明なコードは、テキスト(エンコーディングを含む)を行ごと(行末の任意の選択)に解析する方法を知っています。
実際、新しい行で終わる場合、(理論的には)EOLとEOFの間に空の最終行がありますか?熟考する者...
最後に改行のないファイルに関する実際的なプログラミングの問題もあります。Bash read
組み込み(他のread
実装については知りません)は期待どおりに動作しません。
printf $'foo\nbar' | while read line
do
echo $line
done
これは印刷のみfoo
です!その理由はread
、最後の行に遭遇すると内容を書き込みますが、$line
EOFに達したため終了コード1を返すためです。これはwhile
ループを壊すので、そのecho $line
部分に到達することはありません。この状況を処理する場合は、次のことを行う必要があります。
while read line || [ -n "${line-}" ]
do
echo $line
done < <(printf $'foo\nbar')
つまり、ファイルの終わりに空でない行があるために失敗したecho
場合read
に実行します。当然、この場合、入力にはなかった出力に改行が1つ追加されます。
(テキスト)ファイルが改行で終わる必要があるのはなぜですか?
同様に多くの人によって表現されています:
多くのプログラムはうまく動作しないか、それがなければ失敗します。
ファイルを適切に処理するプログラムでも、末尾'\n'
にがありませんが、ツールの機能はユーザーの期待に応えない可能性があります。これは、このコーナーケースでは不明確な場合があります。
プログラムがfinalを許可'\n'
しないことはめったにありません(私は知りません)。
しかし、これは次の質問を引き起こします:
改行のないテキストファイルに対してコードは何をすべきですか?
最も重要- テキストファイルが改行で終わると想定するコードを記述しないでください。 ファイルがフォーマットに準拠していると仮定すると、データの破損、ハッカーの攻撃、クラッシュが発生します。例:
// Bad code
while (fgets(buf, sizeof buf, instream)) {
// What happens if there is no \n, buf[] is truncated leading to who knows what
buf[strlen(buf) - 1] = '\0'; // attempt to rid trailing \n
...
}
最後のトレーリング'\n'
が必要な場合は、その不在と取られたアクションについてユーザーに警告します。IOWは、ファイルの形式を検証します。注:これには、最大行長、文字エンコードなどの制限が含まれる場合があります。
欠落しているfinalのコードの処理を明確に文書化します'\n'
。
可能な限り、末尾のないファイルを生成しないでください'\n'
。
ここでは非常に遅いですが、ファイル処理で1つのバグに直面しただけで、ファイルが空の改行で終わっていないことが原因でした。私たちはしてテキストファイルを処理し、sed
かつsed
無効なJSON構造の原因と状態を失敗するプロセスの残りを送った出力からの最後の行を省略しました。
私たちがやっていたことは、
1つのサンプルファイルは言う:foo.txt
そのjson
中にいくつかのコンテンツ。
[{
someProp: value
},
{
someProp: value
}] <-- No newline here
ファイルは未亡人のマシンで作成され、ウィンドウスクリプトはPowerShellコマンドを使用してそのファイルを処理していました。すべて良い。
sed
コマンドを使用して同じファイルを処理したときsed 's|value|newValue|g' foo.txt > foo.txt.tmp
新しく生成されたファイルは
[{
someProp: value
},
{
someProp: value
ブーム、JSONが無効なため、残りのプロセスは失敗しました。
したがって、常にファイルを空の改行で終了することをお勧めします。
ルールは、末尾の改行なしでファイルを解析することが困難だった時代から来たという印象を常に感じていました。つまり、行末がEOL文字またはEOFによって定義されたコードを作成することになります。行がEOLで終わっていると仮定する方が簡単でした。
ただし、このルールは改行を必要とするCコンパイラから派生したものだと思います。また、「ファイルの終わりに改行がない」コンパイラの警告で指摘されているように、#includeは改行を追加しません。
私見、それは個人的なスタイルと意見の問題です。
昔は改行しませんでした。保存された文字は、その14.4Kモデムによる速度の向上を意味します。
後で、改行を入れて、Shift +下矢印を使用して最終行を選択しやすくしました。