计算多个文件中的注释数,包括多行注释

时间:2018-10-31 21:34:42

标签: powershell

我正在尝试编写一个脚本,该脚本计算多个文件中的所有注释,包括单行(//)和多行(/ * * /)注释并打印出总数。因此,以下文件将返回4

// Foo

var text = "hello world";

/*
   Bar
*/

alert(text);

我需要在代码中包含特定的文件类型,并排除某些文件类型和文件夹。

我当前的代码是:

(   gci -include *.cs,*.aspx,*.js,*.css,*.master,*.html -exclude *.designer.cs,jquery* -recurse `
    | ? { $_.FullName -inotmatch '\\obj' } `
    | ? { $_.FullName -inotmatch '\\packages' } `
    | ? { $_.FullName -inotmatch '\\release' } `
    | ? { $_.FullName -inotmatch '\\debug' } `
    | ? { $_.FullName -inotmatch '\\plugin-.*' } `
    | select-string "^\s*//" `
).Count

如何更改它以获取多行注释?

更新:我的最终解决方案(比我要的要强一些)如下:

$CodeFiles = Get-ChildItem -include *.cs,*.aspx,*.js,*.css,*.master,*.html -exclude *.designer.cs,jquery* -recurse |
    Where-Object { $_.FullName -notmatch '\\(obj|packages|release|debug|plugin-.*)\\' }

$TotalFiles = $CodeFiles.Count

$IndividualResults = @()

$CommentLines = ($CodeFiles | ForEach-Object{ 
    #Get the comments via regex
    $Comments = ([regex]::matches(
        [IO.File]::ReadAllText($_.FullName), 
        '(?sm)^[ \t]*(//[^\n]*|/[*].*?[*]/)'
    ).Value -split '\r?\n') | Where-Object { $_.length -gt 0 }

    #Get the total lines
    $Total = ($_ | select-string .).Count
    #Add to the results table
    $IndividualResults += @{
        File = $_.FullName | Resolve-Path -Relative; 
        Comments = $Comments.Count;
        Code = ($Total - $Comments.Count)
        Total = $Total
    }
    Write-Output $Comments
}).Count

$TotalLines = ($CodeFiles | select-string .).Count

$TotalResults = New-Object PSObject -Property @{
    Files = $TotalFiles
    Code = $TotalLines - $CommentLines
    Comments = $CommentLines
    Total = $TotalLines
}

Write-Output (Get-Location)
Write-Output $IndividualResults | % { new-object PSObject -Property $_} | Format-Table File,Code,Comments,Total
Write-Output $TotalResults | Format-Table Files,Code,Comments,Total

2 个答案:

答案 0 :(得分:2)

要清楚:使用字符串匹配/正则表达式并不是检测JavaScript / C#代码中注释的完全可靠的方法,因为可能存在误报(例如var s = "/* hi */";);为了进行可靠的解析,您需要一个语言解析器。

如果这无关紧要,并且足以在其行上检测注释(以开头开始),并且可以选择以空格开头,那么这是一种简洁的解决方案(PSv3 +):

(Get-ChildItem -include *.cs,*.aspx,*.js,*.css,*.master,*.html -exclude *.designer.cs,jquery* -recurse |
  Where-Object { $_.FullName -notmatch '\\(obj|packages|release|debug|plugin-.*)' } |
    ForEach-Object { 
      [regex]::matches(
        [IO.File]::ReadAllText($_.FullName), 
        '(?sm)^[ \t]*(//[^\n]*|/[*].*?[*]/)'
      ).Value -split '\r?\n'
    }
 ).Count

使用示例输入,ForEach-Object命令产生4
删除^[ \t]*部分以匹配一行开始的注释。

  • 该解决方案使用[IO.File]::ReadAllText()作为一个字符串读取每个输入文件,然后使用[regex]::Matches()方法提取所有(可能跨行)注释。

    • 注意:您可以使用Get-Content -Raw代替单个字符串读取文件,但这要慢得多,尤其是在处理多个文件时。

    • 正则表达式使用内联选项sm(?sm))分别使.也匹配换行符并锚定{{1} }和^分别匹配。

    • $匹配行开头的空格和制表符的任何组合。

    • ^[ \t]*与以//[^\n]*$开头的字符串匹配到该行的末尾。
    • //在多行中匹配一个块注释;请注意 lazy 量词/[*].*?[*]/,它确保结束*?分隔符的 next 实例非常匹配。
  • 然后将匹配的注释(*/)分成几行(.Value),并输出。

  • 然后计算所有文件中的结果行(-split '\r?\n'


关于您尝试过的事情:

您的方法的基本问题是,.Count带有文件信息对象输入(例如Select-String提供)始终不变地逐行处理输入文件 。< / p>

尽管可以通过在Get-ChildItem脚本块中调用Select-String来解决此问题,在该脚本块中,您将每个文件的内容作为单个字符串传递给ForEach-Object,直接如上所示,使用底层正则表达式.NET类型更为有效。

答案 1 :(得分:0)

IMO更好的方法是通过删除单行/多行注释来对净代码行进行计数。

首先,一个处理单个文件并返回上述sample.cs结果的脚本5

((Get-Content sample.cs -raw) -replace "(?sm)^\s*\/\/.*?$" `
  -replace "(?sm)\/\*.*?\*\/.*`n" | Measure-Object -Line).Lines

编辑:在不删除空行的情况下,与总行建立差异

## Q:\Test\2018\10\31\SO_53092258.ps1

$Data = Get-ChildItem *.cs | ForEach-Object {
    $Content = Get-Content $_.FullName -Raw
    $TotalLines = (Measure-Object -Input $Content -Line).Lines
    $CodeLines = ($Content -replace "(?sm)^\s*\/\/.*?$" `
          -replace "(?sm)\/\*.*?\*\/.*`n" | Measure-Object -Line).Lines
    $Comments = $TotalLines - $CodeLines
    [PSCustomObject]@{
        File    = $_.FullName
        Lines   = $TotalLines
        Comments= $Comments
    }
}

$Data
"="*40
"TotalLines={0} TotalCommentLines={1}" -f (
    $Data | Measure-Object -Property Lines,Comments -Sum).Sum

示例输出:

> Q:\Test\2018\10\31\SO_53092258.ps1

File                          Lines Comments
----                          ----- --------
Q:\Test\2018\10\31\example.cs    10        5
Q:\Test\2018\10\31\sample.cs      9        4
============================================
TotalLines=19 TotalCommentLines=9