ファイルの末尾に行を追加すると、テキストが新しい行を書き込まない場合があります。

ファイルの末尾に行を追加すると、テキストが新しい行を書き込まない場合があります。

場合によっては、ファイルに新しい行を追加しようとすると、実際に追加した新しい行が最後の行の末尾に挿入されることがわかります。

たとえば、追加する前のファイルは次のようになります。

more /etc/hosts
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6

次に、次を追加します。

echo "182.2.3.4 host_1" >>/etc/hosts

私達は次を得ました:

more /etc/hosts
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6182.2.3.4 host_1

おそらく最も簡単な解決策は次のとおりです。

echo  >> /etc/hosts

しかし、他の解決策を手に入れることができてうれしいです。

答え1

これは、元のファイルの最後の行末に改行文字がないためです。echo "182.2.3.4 host_1"は最初に1つを追加しませんが(後ろに1つを追加しますが...host_1)、結果ファイルは追加しません。

この問題のため、厳密に言えば、標準では、改行文字で終わるには「行」が必要です。、常にその場所に置く必要があります。一部のユーティリティは、最後の改行なしで予期しない動作を引き起こす可能性がありwc -lますread。一部のエディタは常に追加しますが、一部のエディタはそうではありません。そうでない場合は、最後の行の後にEnterを押すか、カーソルをその下の「空行」に移動して、改行があるかどうかを確認してください。

同様のファイルは、以下を使用して回復できます。

perl -i  -pe '$_ .= "\n" unless /\n$/' file-maybe-without-nl.txt

末尾の改行文字がすでに存在する場合は、そのままにしてください。 (awk 1 < file.txt > fixed.txtまた動作しているようですが、awkには標準の内部編集機能はありませんが、sed使用方法がわかりません。)

もちろん、、echo >> /etc/hostsのように無条件に改行を追加することもできますがecho -e '\n182.2.3.4 host_1' >> /etc/hosts、ファイルを追加する前に形式がうまくいっていると途中に偽空白行が追加されます。

行全体を読み取らずに最後の改行を確認する1つの方法は、最後の行(または行の一部)または最後の文字のみを使用またはインポートすることtail -n1です。tail -c1それから

[ "$(tail -c1 "$f")" = "" ] || echo >> "$f"

必要に応じて追加して使用できます。 (これは改行文字を食べるコマンドの置き換えに依存するので、改行文字がある場合は拡張は空です。はい) または以下を使用しますread(改行文字が表示されない場合はエラー状態を返します).

tail -c1 file | read -r tmp || echo >> file

tail(後者のコマンドと完全なコマンドのアイデアは、次のブログ記事で借りました。https://backreference.org/2010/05/23/sanitizing-files-with-no-trailing-newline/)

CR(キャリッジリターン)文字は、Unixファミリーシステムで行ターミネーターとして使用される改行/LF(改行)文字とは異なります。 (CR+LF は DOS および Windows の行終端として使用されます。)

関連情報