文章目录
上一篇文章介绍了,如何使用工具检测项目中的代码重复度,可见博文
使用jscpd统计代码重复度。
本文将探索下,如何在前端项目统计代码的行数,目前博主所知的较方便的方式大概有6种,每种方式都对应的是不同的使用场景,下面将一一为大家介绍。
直接在项目文件目录下使用命令行进行统计,是比较方便的,能统计所有的代码总行数、以及每个文件的行数、进行条件过滤统计等等,比如 find 和 wc。
find 和 wc 两个命令是 Linux 和 Unix 系统中的常用命令,而在Windows系统下,如果安装了 Git,可以调出 Git Bash 工具,使用 find 和 wc 命令统计代码行数。
Git Bash可以在Windows系统中提供类似于Unix shell的命令行环境,包含了Git和Unix工具常用的命令,方便管理、提高效率。
当前一般前端项目,核心业务代码基本都在 src 目录下,我们进入该目录,直接执行以下命令:
find . -type f -print | xargs wc -l
该命令,可以直接读取到所有的文件,并显示每个文件的代码行数,以及所有文件的总行数,如下图所示。

这是简单的文件读取,还可以通过各种条件过滤。
如进行文件格式过滤,以下命令只读取 .js 和 .ts 格式的文件:
find . "(" -name "*.js" -or -name "*.ts" ")" -print | xargs wc -l
过滤代码文件中的空行,使用 grep -v "^$":
find . "(" -name "*.js" -or -name "*.ts" ")" -print | xargs | grep -v "^$" | wc -l
进行目录过滤,比如不统计 node_modules 目录:
find . -name "*.js" | grep -v "node_modules" | xargs wc -l
find:在给定路下寻找匹配的文件,-name表示文件名,-type文件类型
wc:统计文件中的文件行数、字数和字符数,-l统计文件的行数
grep:逐行搜索,找出匹配的内容,-v表示不匹配
在Windows下,还可以使用 PowerShell 命令行工具来统计项目的代码行数。
在项目的 src 目录下,我们只需要在该目录下运行 PowerShell 工具,打开命令行窗口,输入以下命令:
(Get-ChildItem -Recurse -File | Get-Content | Measure-Object).Count
## 63240
通过该命令,可以输出 src 目录下所有文件的行数总和,如果要过滤空行,可以使用 -Line 参数选项:
(Get-ChildItem -Recurse -File | Get-Content | Measure-Object -Line).Lines
## 58691
这里输出的就是不包含空行的代码行数。
如果要过滤文件格式,可以使用通配符:
(Get-ChildItem -Recurse "*.ts","*.js" | Get-Content | Measure-Object).Count
上面的格式过滤方式,无法使用路径,所以也可以使用 Where-Object 命令来过滤文件格式,可以限定路径为 .\src,如下所示:
(Get-ChildItem .\src -Recurse | Where-Object {$_.Name -like "*.ts" -or $_.Name -like "*.js"} | Get-Content | Measure-Object).Count
如果要输出每个文件的行数:
Get-ChildItem -Recurse -File | ForEach-Object {Write-Output $_.FullName $(Get-Content $_.FullName | Measure-Object).Count}

Get-ChildItem:获取指定目录中的文件和子目录的列表。在
PowerShell中还可以使用dir命令,效果差不多。
-Recurse:命令参数,用于在搜索目录时递归子目录。
Get-Content:读取文本文件的内容,包含文件行数、字符、字节等数据。
Measure-Object:用于对一组对象进行测量和计算,如进行求和。
Where-Object:根据指定条件筛选过滤对象集合的数据。
ForEach-Object:迭代命令,对于输入的对象组中的每个对象进行指定操作,可用于遍历文件。
Write-Output:将指定的字符串或值输出到PowerShell控制台。
除了以上两种命令行统计方案以外,还可以使用git命令来统计代码行数,命令也很简单,主要使用到以下两个命令:
如下,统计项目中所有文件的总代码行数:
git ls-files | xargs cat | wc -l
## 58927
但需要注意的是:如果使用git统计,需要代码已经提交入库到git仓库,否则,统计命令会报错:
git ls-files | xargs cat | wc -l
## fatal: not a git repository (or any of the parent directories): .git
统计每个文件的代码行数,命令如下:
git ls-files | xargs wc -l

显示文件的行数以及总代码行数。
从上面命令可看出,使用 git ls-files 和前文提到的 find 较相似,也可以对它的结果进行过滤。
git ls-files '*.tsx' '*.js' | grep -v 'src/assets' | xargs wc -l
以上命令,统计文件格式为 .tsx 和 .js 的文件,并且会过滤掉 src/assets 目录下的文件,可以通过这种方式进行自定义的筛选。
也可以使用git log命令,统计对应分支下的修改代码的行数。
git log --no-merges --pretty=tformat: --numstat | awk '{ add += $1; subs += $2; loc += $1 - $2 } END { printf "added lines: %s, removed lines: %s, total lines: %s\n", add, subs, loc }'
这里统计了当前分支下的代码行数,包含增加的行数、删除的行数、以及代码总行数,如下图所示:

也可以增加一些参数,通过这些参数进行条件过滤:
–no-merges:是去除该提交中merges的代码,因为开发人员有可能会merge其他分支的代码,此时应该去除
–since= --until=:是要统计修改记录的开始和结束时间,当统计某个迭代,就是迭代开始时间和结束时间
–author:是指修改代码的人 过滤多人时使用|分开
–pretty=:控制显示的记录格式
–numstat:对增加和删除的行数进行统计 第一列显示的是增加的行数 第二列显示的是删除的行数
git log master --no-merges --since=2023-03-01 --until=2023-3-26 --author="zuozhe" --pretty=tformat: --numstat | awk '{ add += $1 ; subs += $2 ; loc += $1 - $2 } END { printf "added lines: %s removed lines : %s total lines: %s\n",add,subs,loc }'
## added lines: 28750 removed lines : 7767 total lines: 20983
如上命令所示,统计了 master 分支下,时间从 2023-03-01 到 2023-3-26之间,提交人为 zuozhe 的所有修改过的代码行数。
现在的代码编辑器也有提供一些插件,用于统计代码行数,比如博主使用的 VS Code,就很方便。
这里介绍 VS Code Counter 插件,它能统计项目代码行数、注释行数、以及空行,并且还会展示每个文件的行数以及分不同格式的文件显示。
首先,在插件中心安装该插件,然后使用快捷键 ctrl + shift + p,在输入框选择 VSCodeCounter: Count lines in directory,接着会出现项目目录输入框,默认是当前工作目录,可以更改。


确定好项目路径以后,回车就会显示已选路径下的项目文件代码的统计行数,以 .md 文件的形式展示出来,如下图:

该插件会在当前目录下,生成一个名为 .VSCodeCounter 的目录,里面放置生成的各种代码统计数据,可以自行查询。
前文提到上一篇博文有介绍如何统计代码重复度,使用了 jscpd 工具库,它当然也有统计项目代码行数的能力。
如下图所示,会显示整个项目总的代码行数,Total 行,更多的使用可查看上篇博文。

除了使用以上5种方式以外,我们也可以自己动手,实现一个读取项目代码行数的工具。
而要想实现一个简单的代码行数的统计工具,只需要以下三个步骤:
\n 进行判断即可对于前端同学,使用 nodejs 可以很好的完成这个事情,如迭代文件,代码如下:
// 可以通过执行命令传入目录参数
const params = process.argv.splice(2)
const root = params[0]
// 遍历读取文件
let stat = fs.statSync(root)
if (stat.isDirectory()) {
let files = fs.readdirSync(root)
for (let file of files) {
file = `${root}/${file}`
const dirStat = fs.statSync(file)
if (dirStat.isDirectory()) {
queryAllFiles(file)
} else {
// 读取文件行数
}
}
} else {
// 读取文件行数
}
下面是,读取文件内容和行数:
// 读取文件内容,通过 `\n` 换行符分割内容后,统计长度,即行数
let fileContent = fs.readFileSync(path)
fileContent = fileContent.toString()
const fileLines = fileContent.split('\n')
const lines = fileLines.length
console.log(path + ' ' + lines)
读取了每一个文件的行数,我们只需要对它们进行累加就可以统计出总的代码行数。
还可以统计代码注释,这里以前端的JS代码为示例,使用正则表达式,判断一行代码是否注释:
const reg = new RegExp('^(//|/\\*|\\*|\\*/)', 'g')
const commentLines = fileLines.filter(line => reg.test(line.trimStart())).length
注意,这里注释的判断,使用的JS代码相关的注释方式://、/*、*、*/,TS代码也一样适用。
如果是使用其他注释方式的代码,需要定义对应的过滤。
空行的判断,也很简单,只需要判断一行没有内容即可:
const blankLines = fileLines.filter(line => line.trim() === '').length
如果还要加条件进行过滤筛选,也比较方便,只需要在循环迭代送文件时进行过滤。
比如我们需要忽略掉 'node_modules'、'dist'等目录:
// 定义过滤的目录,也可以使用配置文件、命令参数等方式
const ignores = ['node_modules', 'dist']
// 文件迭代时,忽略相应目录
for (let file of files) {
const isNotIgnore = ignores.indexOf(file) > -1
if (isNotIgnore) {
continue
}
// ...
}
筛选文件和目录的方式较类似,使用不同的比较方式而已。
文件格式的过滤:
// 只统计 js 和 ts 的代码文件
const formats = ['.js', '.ts']
if (stat.isFile()) {
let ext = path.extname(file)
if (formats.indexOf(ext) !== -1) {
// 读取文件内容和行数
// ...
}
}
看看简单的执行结果,如下图所示:

六种不同的方式,都能方便的统计代码行数,但也各有特点。
如 find 命令行适用不同系统,而 PowerShell 在Windows系统下可用;jscpd 统计代码行数和重复度。
安装了 Git 工具的,可以使用 git log 统计代码的修改行数、不同人员和时间段的各种提交修改等。
代码编辑器,有各种插件工具,除了统计代码行数,还能区分文件格式、注释行数、空行,也比较直观方便。
自己实现一个统计工具,能够实现更多的功能,并进行定制化处理,或者集成到构建工具中等等,满足更多需求。
我试图获取一个长度在1到10之间的字符串,并输出将字符串分解为大小为1、2或3的连续子字符串的所有可能方式。例如:输入:123456将整数分割成单个字符,然后继续查找组合。该代码将返回以下所有数组。[1,2,3,4,5,6][12,3,4,5,6][1,23,4,5,6][1,2,34,5,6][1,2,3,45,6][1,2,3,4,56][12,34,5,6][12,3,45,6][12,3,4,56][1,23,45,6][1,2,34,56][1,23,4,56][12,34,56][123,4,5,6][1,234,5,6][1,2,345,6][1,2,3,456][123
如何在buildr项目中使用Ruby?我在很多不同的项目中使用过Ruby、JRuby、Java和Clojure。我目前正在使用我的标准Ruby开发一个模拟应用程序,我想尝试使用Clojure后端(我确实喜欢功能代码)以及JRubygui和测试套件。我还可以看到在未来的不同项目中使用Scala作为后端。我想我要为我的项目尝试一下buildr(http://buildr.apache.org/),但我注意到buildr似乎没有设置为在项目中使用JRuby代码本身!这看起来有点傻,因为该工具旨在统一通用的JVM语言并且是在ruby中构建的。除了将输出的jar包含在一个独特的、仅限ruby
我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i
在rails源中:https://github.com/rails/rails/blob/master/activesupport/lib/active_support/lazy_load_hooks.rb可以看到以下内容@load_hooks=Hash.new{|h,k|h[k]=[]}在IRB中,它只是初始化一个空哈希。和做有什么区别@load_hooks=Hash.new 最佳答案 查看rubydocumentationforHashnew→new_hashclicktotogglesourcenew(obj)→new_has
我正在编写一个包含C扩展的gem。通常当我写一个gem时,我会遵循TDD的过程,我会写一个失败的规范,然后处理代码直到它通过,等等......在“ext/mygem/mygem.c”中我的C扩展和在gemspec的“扩展”中配置的有效extconf.rb,如何运行我的规范并仍然加载我的C扩展?当我更改C代码时,我需要采取哪些步骤来重新编译代码?这可能是个愚蠢的问题,但是从我的gem的开发源代码树中输入“bundleinstall”不会构建任何native扩展。当我手动运行rubyext/mygem/extconf.rb时,我确实得到了一个Makefile(在整个项目的根目录中),然后当
我在我的Rails项目中使用Pow和powifygem。现在我尝试升级我的ruby版本(从1.9.3到2.0.0,我使用RVM)当我切换ruby版本、安装所有gem依赖项时,我通过运行railss并访问localhost:3000确保该应用程序正常运行以前,我通过使用pow访问http://my_app.dev来浏览我的应用程序。升级后,由于错误Bundler::RubyVersionMismatch:YourRubyversionis1.9.3,butyourGemfilespecified2.0.0,此url不起作用我尝试过的:重新创建pow应用程序重启pow服务器更新战俘
我已经像这样安装了一个新的Rails项目:$railsnewsite它执行并到达:bundleinstall但是当它似乎尝试安装依赖项时我得到了这个错误Gem::Ext::BuildError:ERROR:Failedtobuildgemnativeextension./System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/bin/rubyextconf.rbcheckingforlibkern/OSAtomic.h...yescreatingMakefilemake"DESTDIR="cleanmake"DESTDIR="
我已经在Sinatra上创建了应用程序,它代表了一个简单的API。我想在生产和开发上进行部署。我想在部署时选择,是开发还是生产,一些方法的逻辑应该改变,这取决于部署类型。是否有任何想法,如何完成以及解决此问题的一些示例。例子:我有代码get'/api/test'doreturn"Itisdev"end但是在部署到生产环境之后我想在运行/api/test之后看到ItisPROD如何实现? 最佳答案 根据SinatraDocumentation:EnvironmentscanbesetthroughtheRACK_ENVenvironm
我的主要目标是能够完全理解我正在使用的库/gem。我尝试在Github上从头到尾阅读源代码,但这真的很难。我认为更有趣、更温和的踏脚石就是在使用时阅读每个库/gem方法的源代码。例如,我想知道RubyonRails中的redirect_to方法是如何工作的:如何查找redirect_to方法的源代码?我知道在pry中我可以执行类似show-methodmethod的操作,但我如何才能对Rails框架中的方法执行此操作?您对我如何更好地理解Gem及其API有什么建议吗?仅仅阅读源代码似乎真的很难,尤其是对于框架。谢谢! 最佳答案 Ru
我们的git存储库中目前有一个Gemfile。但是,有一个gem我只在我的环境中本地使用(我的团队不使用它)。为了使用它,我必须将它添加到我们的Gemfile中,但每次我checkout到我们的master/dev主分支时,由于与跟踪的gemfile冲突,我必须删除它。我想要的是类似Gemfile.local的东西,它将继承从Gemfile导入的gems,但也允许在那里导入新的gems以供使用只有我的机器。此文件将在.gitignore中被忽略。这可能吗? 最佳答案 设置BUNDLE_GEMFILE环境变量:BUNDLE_GEMFI