我一直在研究如何从最后一行可能没有尾随换行符的文件中正确读取行。已经找到答案了读取可能不以换行符结尾的面向行的文件。
但是,我有第二个目标,那就是排除行首的注释,并找到了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
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