计算bash中的(非空白)代码行


151

在Bash中,如何计算项目中非空行的数量?


1
以下许多解决方案仅适用于一个文件(例如foo.c)。对项目中的总行数有什么想法(例如,目录结构中的许多文件,但不包括二进制文件)?
–solutionPuzzles

5
@solvingPuzzles我想我可以回答这一部分。对于适用于一个文件的任何解决方案,例如“ cat FILE | sed blah”,您可以通过使用列出要操作的文件名的命令替换“ cat FILE”来处理许多文件,例如“ find。-name'* .py'”,并将其通过管道传递到“ xargs cat”。例如“查找。-name'* .py'| xargs cat | sed'/ ^ \ s * $ / d'| wc -l”
Jonathan Hartley 2012年

2
@JonathanHartley @solvingPuzzles也有类似的程序sloccloc这些程序可以用来计算这些代码行数。
AsTeR

此处的OP:当我第一次问这个问题时,“ cloc”在Python代码上做得并不出色。如今真棒。
乔纳森·哈特利

cloc也可以作为npm模块使用,并节省大量时间。
克里希纳·维杜拉

Answers:


193
cat foo.c | sed '/^\s*$/d' | wc -l

如果您认为注释为空行:

cat foo.pl | sed '/^\s*#/d;/^\s*$/d' | wc -l

虽然,这取决于语言。


24
不知道为什么在那儿使用猫。使用foo.c或foo.pl作为传递给sed的文件名。sed'/ ^ \ s * $ / d'foo.c | wc -l
Andy Lester

28
养成习惯 我从左到右读取管道,这意味着我通常从cat开始,然后是action,action,action等。显然,最终结果是相同的。
Michael Cramer

32
要对所有子文件夹中的所有文件执行此操作并排除带有“ //”的注释,请将此命令扩展为:find。-type f -name'* .c'-exec cat {} \; | sed'/ ^ \ s *#/ d; / ^ \ s * $ / d; / ^ \ s * \ / \ // d'| wc -l
Benjamin Intal 2010年

11
您无需UUOC即可从左到右阅读:< foo.pl sed 'stuff' | wc -l
jw013 2011年

22
一般来说,UUOC不重要,但可读性很重要。
andersand

52
#!/bin/bash
find . -path './pma' -prune -o -path './blog' -prune -o -path './punbb' -prune -o -path './js/3rdparty' -prune -o -print | egrep '\.php|\.as|\.sql|\.css|\.js' | grep -v '\.svn' | xargs cat | sed '/^\s*$/d' | wc -l

以上将为您提供项目(当前文件夹和所有子文件夹递归)的代码行总数(已删除空白行)。

在上面的“ ./blog”、“./punbb”、“./js/3rdparty”和“ ./pma”中,我未将代码写入黑名单。此外,.php,.as,.sql,.css,.js是要查看的文件的扩展名。任何扩展名不同的文件都将被忽略。


1
Rails应用的变体:find。-path'./log'-prune -o -path'./trunk'-prune -o -path'./branches'-prune -o -path'./vendor'-prune -o -path'./tmp '-prune -o -print | egrep'\ .rb | \ .erb | \ .css | \ .js | \ .yml'| grep -v'svn'| xargs猫| sed'/ ^ \ s * $ / d'| 厕所-l
poseid

1
您需要$在grep(...\.js$|...)中添加a ,否则它将匹配feature.js.swp
Xeoncross

您忘记了锚定,因此其中包含错误的文件。还有一个更简单的锚定版本:find . | egrep '.\.c$|.\.h$' | xargs cat | sed '/^\s*$/d' | wc -l
Mark Jeronimus

36

如果要使用Shell脚本以外的其他方法,请尝试CLOC

cloc计算许多编程语言中源代码的空行,注释行和物理行。它完全用Perl编写,没有Perl v5.6和更高版本的标准发行版(cloc内嵌了一些外部模块的代码)之外的任何依赖项,因此非常易于移植。


2
当我第一次问这个问题时,“ cloc”将Python文档字符串视为代码行,这不是最理想的恕我直言。现在,现代版本的“ cloc”将Python文档字符串视为注释,我对此非常满意。
乔纳森·哈特利

这是正确的答案!我只是尝试过cloc,它做得很好。
LeeMobile

31

使用通用的Shell实用程序可以通过多种方法来执行此操作。

我的解决方案是:

grep -cve '^\s*$' <file>

这会在<file>中搜索与模式(-e)'^ \ s * $'匹配的不匹配(-v)行,这是一行的开头,然后是0个或多个空格字符在一行的末尾(即除空白外没有其他内容),并显示匹配行数(-c)而不是匹配行本身。

该方法相对于涉及到的方法的优点wc是,您可以指定多个文件并为每个文件获得单独的计数:

$ grep -cve '^\s*$' *.hh

config.hh:36
exceptions.hh:48
layer.hh:52
main.hh:39

2
谢谢!顺便说一句,wc确实为每个给定的文件提供了计数以及总数。
乔纳森·哈特利

1
但是,如果您正在向其中传输文件,则不是这样,按照标准,计数仅为一个文件。
SpoonMeiser

我认为这是最好的答案。
simhumileco

-e没有必要。那是图案的正常位置,您不会对其进行任何时髦的处理。但是,如果这是您的风格,那么明确就没错。
Jacktose

13

'wc'计算行,单词,字符,因此要计算所有行(包括空白行),请使用:

wc *.py

要过滤出空行,可以使用grep:

grep -v '^\s*$' *.py | wc

'-v'告诉grep输出所有行,除了那些匹配'^'的行是行的开始'\ s *'是零或多个空格字符'$'是行的结尾* .py是我的示例您希望计数的所有文件(当前目录中的所有python文件)通过管道输出到wc。就行了。

我在回答我自己的(真正的)问题。找不到涵盖此内容的stackoverflow条目。


5
\ W不是空格的匹配项,它匹配非单词字符。与\ w(单词字符)相反。\ W将匹配任何非字母数字或下划线的内容,因此不会执行您在此处声称的操作。您的意思是\ s
SpoonMeiser

9

此命令计数非空行数。
cat fileName | grep -v ^$ | wc -l
grep -v ^ $正则表达式函数忽略空行。


这个答案是最直截了当的
最棒的是

2
cat该链没有必要:grep -v ^$ fileName | wl -l
Aethalides

7
也没有必要,wc -l因为grep具有-cgrep -vc ^$ fileName
Jacktose


5
cat 'filename' | grep '[^ ]' | wc -l

应该可以解决问题


3
当您首先将文件名作为参数传递给grep时,为什么要使用cat并将文件通过管道传输到grep中?
SpoonMeiser

是的,这只是我周围的一个旧别名...它与您的解决方案基本相同,而不是使用逆
运算法

4
awk '/^[[:space:]]*$/ {++x} END {print x}' "$testfile"

1
我之所以投票赞成这是因为我从没看过有人在awk脚本中使用预增量,但是不幸的是,这仅算空白行。:)你的意思是awk '!/^[[:space:]]*$/{++x} END{print x}'。或者,如果您真的讨厌底片,awk '{y++} /^[[:space:]]*$/{++x} END{print y-x}';)
dannysauer 2013年

4
grep -cvE '(^\s*[/*])|(^\s*$)' foo

-c = count
-v = exclude
-E = extended regex
'(comment lines) OR (empty lines)'
where
^    = beginning of the line
\s   = whitespace
*    = any number of previous characters or none
[/*] = either / or *
|    = OR
$    = end of the line

我发布此邮件是因为其他选项给了我错误的答案。这与我的java源代码一起工作,其中注释行以/或*开头(我在多行注释的每一行上都使用*)。


这是一个可行的解决方案。唯一要注意的是:它不计算多行注释
Amol

2

这是一个Bash脚本,用于计算项目中的代码行。它递归地遍历源代码树,并且排除使用“ //”的空行和单行注释。

# $excluded is a regex for paths to exclude from line counting
excluded="spec\|node_modules\|README\|lib\|docs\|csv\|XLS\|json\|png"

countLines(){
  # $total is the total lines of code counted
  total=0
  # -mindepth exclues the current directory (".")
  for file in `find . -mindepth 1 -name "*.*" |grep -v "$excluded"`; do
    # First sed: only count lines of code that are not commented with //
    # Second sed: don't count blank lines
    # $numLines is the lines of code
    numLines=`cat $file | sed '/\/\//d' | sed '/^\s*$/d' | wc -l`

    # To exclude only blank lines and count comment lines, uncomment this:
    #numLines=`cat $file | sed '/^\s*$/d' | wc -l`

    total=$(($total + $numLines))
    echo "  " $numLines $file
  done
  echo "  " $total in total
}

echo Source code files:
countLines
echo Unit tests:
cd spec
countLines

这是我的项目的输出结果:

Source code files:
   2 ./buildDocs.sh
   24 ./countLines.sh
   15 ./css/dashboard.css
   53 ./data/un_population/provenance/preprocess.js
   19 ./index.html
   5 ./server/server.js
   2 ./server/startServer.sh
   24 ./SpecRunner.html
   34 ./src/computeLayout.js
   60 ./src/configDiff.js
   18 ./src/dashboardMirror.js
   37 ./src/dashboardScaffold.js
   14 ./src/data.js
   68 ./src/dummyVis.js
   27 ./src/layout.js
   28 ./src/links.js
   5 ./src/main.js
   52 ./src/processActions.js
   86 ./src/timeline.js
   73 ./src/udc.js
   18 ./src/wire.js
   664 in total
Unit tests:
   230 ./ComputeLayoutSpec.js
   134 ./ConfigDiffSpec.js
   134 ./ProcessActionsSpec.js
   84 ./UDCSpec.js
   149 ./WireSpec.js
   731 in total

请享用!- 柯伦


1

这有点取决于项目中文件的数量。理论上您可以使用

grep -c '.' <list of files>

您可以在其中使用find实用程序填充文件列表。

grep -c '.' `find -type f`

将为您提供每个文件的行数。


1
。匹配空白。仅当您认为仅包含空格的行是非空白的行时,此解决方案才有效(从技术上讲,它是空白行),尽管可能不是您想要的。
SpoonMeiser

1

脚本以递归方式计算当前目录中带有特定文件扩展名的所有非空白行:

#!/usr/bin/env bash
(
echo 0;
for ext in "$@"; do
    for i in $(find . -name "*$ext"); do
        sed '/^\s*$/d' $i | wc -l ## skip blank lines
        #cat $i | wc -l; ## count all lines
        echo +;
    done
done
echo p q;
) | dc;

用法示例:

./countlines.sh .py .java .html

感谢@Andy Lester(您的评论+1)获取食谱的“非空白”部分。
基思·品森

也感谢@Michael Cramer(您的帖子+1)最初发布了(稍微冗长一些)“非空白”解决方案。
基思·品森

1

如果想要整个项目中给定文件扩展名的所有文件的所有非空白行的总和:

while read line
do grep -cve '^\s*$' "$line"
done <  <(find $1 -name "*.$2" -print) | awk '{s+=$1} END {print s}'

第一个arg是项目的基本目录,第二个是文件扩展名。用法示例:

./scriptname ~/Dropbox/project/src java

它仅是先前解决方案的集合。


通过在每个文件中的每行一次启动grep,此人获得了最多的fork + exec调用奖。;)
dannysauer 2013年

0
grep -v '^\W*$' `find -type f` | grep -c '.' > /path/to/lineCountFile.txt

给出当前目录及其子目录中所有文件的总数。

HTH!


\ W是非单词字符;例如${-[*]} + $@,这不会与匹配。这肯定是世界上某个地方的有效代码。;)您的意思是空格。
dannysauer

0

这给出了行数的计数而没有空白行:

grep -v ^$ filename wc -l | sed -e 's/ //g' 


-3

在Linux上已经有一个名为“ wc”的程序。

只是

wc -l *.c 

它为您提供了总行数和每个文件的行数。


3
嘿。“ wc”本身不会搜索子目录,也不会过滤出空白行,这两个行都是在问题中明确要求的。
乔纳森·哈特利

wc计算空行。OP希望计算非空白行。他确实想使用wc,但是只有在使用sed
EhevuTov 2012年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.