web-dev-qa-db-ja.com

ファイルの最後の行に末尾の改行文字を追加するという副作用のあるGrepコマンド

最後の行に改行文字がない可能性のあるファイルから行を正しく読み取る方法について、いくつかの調査を行っています。 改行で終わらない可能性のある行指向のファイルを読む で答えを見つけました。

ただし、行頭のコメントを除外するという2番目の目標があり、目標を達成する grep コマンドを見つけました。

$ grep -v '^ *#' file

しかし、このコマンドには(私にとっては予期しない)副次的な動作があることに気づきました。存在しない場合は、最後の行に末尾の改行文字が追加されます。

$ cat file
# This is a commentary
aaaaaa
# This is another commentary
bbbbbb
cccccc

$ od -c file
0000000   #       T   h   i   s       i   s       a       c   o   m   m
0000020   e   n   t   a   r   y  \n   a   a   a   a   a   a  \n   #
0000040   T   h   i   s       i   s       a   n   o   t   h   e   r
0000060   c   o   m   m   e   n   t   a   r   y  \n   b   b   b   b   b
0000100   b  \n   c   c   c   c   c   c  \n
0000111

$ truncate -s -1 file

$ od -c file
0000000   #       T   h   i   s       i   s       a       c   o   m   m
0000020   e   n   t   a   r   y  \n   a   a   a   a   a   a  \n   #
0000040   T   h   i   s       i   s       a   n   o   t   h   e   r
0000060   c   o   m   m   e   n   t   a   r   y  \n   b   b   b   b   b
0000100   b  \n   c   c   c   c   c   c
0000110

$ od -c <(grep -v '^ *#' file)
0000000   a   a   a   a   a   a  \n   b   b   b   b   b   b  \n   c   c
0000020   c   c   c   c  \n
0000025

行頭のコメントを削除するだけでなく、最後の行に末尾の改行文字も追加することに注意してください。

どうしてそうなの?

1
Paulo Tomé

POSIX仕様 は次のように述べています

A line is a sequence of zero or more non-<newline> characters plus a terminating
<newline> character.

grepの動作は予想どおりです。欠落している末尾の改行文字を incomplete line

こちらです:

$ cat file
# This is a commentary
aaaaaa
# This is another commentary
bbbbbb
cccccc

$ od -c file
0000000   #       T   h   i   s       i   s       a       c   o   m   m
0000020   e   n   t   a   r   y  \n   a   a   a   a   a   a  \n   #
0000040   T   h   i   s       i   s       a   n   o   t   h   e   r
0000060   c   o   m   m   e   n   t   a   r   y  \n   b   b   b   b   b
0000100   b  \n   c   c   c   c   c   c  \n
0000111

$ truncate -s -1 file

$ od -c file
0000000   #       T   h   i   s       i   s       a       c   o   m   m
0000020   e   n   t   a   r   y  \n   a   a   a   a   a   a  \n   #
0000040   T   h   i   s       i   s       a   n   o   t   h   e   r
0000060   c   o   m   m   e   n   t   a   r   y  \n   b   b   b   b   b
0000100   b  \n   c   c   c   c   c   c
0000110

$ od -c <(grep '.' file)
0000000   #       T   h   i   s       i   s       a       c   o   m   m
0000020   e   n   t   a   r   y  \n   a   a   a   a   a   a  \n   #    
0000040   T   h   i   s       i   s       a   n   o   t   h   e   r    
0000060   c   o   m   m   e   n   t   a   r   y  \n   b   b   b   b   b
0000100   b  \n   c   c   c   c   c   c  \n
0000111
0
Paulo Tomé