wc -l 如果文件结尾没有换行符,则不会计算文件的最后一行

27

我需要计算一个Unix文件中的所有行数。该文件有3行,但是wc -l只给出了2行。

我知道这是因为它没有统计最后一行,因为它没有结束符。

请问有谁能告诉我如何将那一行也计入总行数?


9
仅供参考:POSIX中对于一行的定义为“一个由零个或多个非<换行符>字符组成并以一个终止的<换行符>字符结束的序列。” - gniourf_gniourf
5个回答

20

grep -c 返回匹配行的数量。只需将空字符串 "" 用作匹配表达式:

grep -c 返回匹配行的数量。只需将空字符串 "" 用作匹配表达式:

$ echo -n $'a\nb\nc' > 2or3.txt
$ cat 2or3.txt | wc -l
2
$ grep -c "" 2or3.txt
3

即使没有-F标志,grep解决方案的速度比最小的awksed版本要快得多,并且非常接近于wc -l本身。 - Toby Speight
对于 ripgrep,使用 rg --fixed-strings --count '' - HappyFace

14

在Unix文件中,最好让所有行以EOL \n结尾。你可以这样做:

{ cat file; echo ''; } | wc -l

或者使用这个awk:

awk 'END{print NR}' file

1
你可以在本地文件系统上执行 echo -n '' >> file - anubhava
1
另一种计数的方法是:{ cat file; echo ''; } | wc -l - anubhava
1
甚至可以使用 awk 'END{print NR}' file - anubhava
1
"{ cat file; echo ''; } | wc -l" 正常工作。谢谢;您能重新发布答案吗?这样我就会接受! - logan
6
请注意,如果文件已经以\n结尾,则{ cat file; echo ''; } | wc -l会给出错误的答案,因为它总是会添加一个额外的行,因此基于awk的解决方案更好。 - PM 2Ring
显示剩余5条评论

7

这种方法可以正确计算行数,无论文件中的最后一行是否以换行符结尾。

awk 会确保在其输出中,每个打印的行都以新行字符结尾。因此,在将行发送到 wc 之前,请确保每行都以换行符结尾:

awk '1' file | wc -l

在这里,我们使用一个简单的awk程序,该程序仅由数字1组成。 awk将解释此神秘语句为“打印行”,并确保存在尾随换行符而实现打印。
示例:
让我们创建一个文件,其中包含三行,每行都以换行符结尾,并计算行数:
$ echo -n $'a\nb\nc\n' >file
$ awk '1' f | wc -l
3

找到了正确的数字。
现在,让我们再试一次,但是去掉最后一个换行符:
$ echo -n $'a\nb\nc' >file
$ awk '1' f | wc -l
3

这仍然提供了正确的数量。 awk 自动纠正缺少换行符的情况,但如果最后一个换行符存在,则保留文件不变。


1
这是最佳答案,因为它不需要修改文件,并且如果不需要,它不会改变计数。 - Bruno Bronosky

2

尊重

我很尊重John1024的回答,并想对其进行扩展。

行数统计函数

我经常比较行数,尤其是从剪贴板中复制出来的。因此,我定义了一个Bash函数。我想修改它以显示文件名,并在传递多个文件时显示总数。但是,这件事对我来说还不够重要。

# semicolons used because this is a condensed to 1 line in my ~/.bash_profile
function wcl(){
  if [[ -z "${1:-}" ]]; then
    set -- /dev/stdin "$@";
  fi;
  for f in "$@"; do
    awk 1 "$f" | wc -l;
  done;
}

Counting lines without the function

# Line count of the file
$ cat file_with_newline    | wc -l
       3

# Line count of the file
$ cat file_without_newline | wc -l
       2

# Line count of the file unchanged by cat
$ cat file_without_newline | cat | wc -l
       2

# Line count of the file changed by awk
$ cat file_without_newline | awk 1 | wc -l
       3

# Line count of the file changed by only the first call to awk
$ cat file_without_newline | awk 1 | awk 1 | awk 1 | wc -l
       3

# Line count of the file unchanged by awk because it ends with a newline character
$ cat file_with_newline    | awk 1 | awk 1 | awk 1 | wc -l
       3

字符计数(为什么不要在wc周围添加包装器)

# Character count of the file
$ cat file_with_newline    | wc -c
       6

# Character count of the file unchanged by awk because it ends with a newline character
$ cat file_with_newline    | awk 1 | awk 1 | awk 1 | wc -c
       6

# Character count of the file
$ cat file_without_newline | wc -c
       5

# Character count of the file changed by awk
$ cat file_without_newline | awk 1 | wc -c
       6

使用函数计算行数

# Line count function used on stdin
$ cat file_with_newline    | wcl
       3

# Line count function used on stdin
$ cat file_without_newline | wcl
       3

# Line count function used on filenames passed as arguments
$ wcl file_without_newline  file_with_newline
       3
       3

0
'wc -l' 不会计算文件的行数。
它只会计算 '\n'(换行符)的数量。
from man page of wc

 -l, --lines
              print the newline counts

你应该使用grep -c '^'来获取行数。
grep -c '^' filename

这似乎只是重复了之前答案中的信息。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接