使用Powershell打印出与RegEx匹配的代码行数

时间:2009-06-09 19:02:52

标签: regex powershell code-comments

我认为我们的源代码中有一堆已注释掉的代码,而不是立即将其删除,我们就把它留下了。现在我想做一些清理。

因此,假设我有一个足够好的RegEx来查找注释(下面的RegEx很简单,我可以根据我们的编码标准对其进行扩展),如何获取我读取的文件的结果并输出以下内容:

  • 文件名
  • 行号
  • 实际的代码行

我认为我有一个答案的基础,但我不知道如何获取我已阅读并使用RegEx解析的文件并以此格式吐出。

我不是在寻找完美的解决方案 - 我只是想找到一大堆注释掉的代码。通过查看结果并查看一堆具有相同名称和顺序行号的文件,我应该能够做到这一点。

$Location = "c:\codeishere"

[regex]$Regex = "//.*;" #simple example - Will expand on this...

$Files = get-ChildItem $Location -include *cs -recurse
foreach ($File in $Files) {
    $contents = get-Content $File
    $Regex.Matches($contents) | WHAT GOES HERE?
}

4 个答案:

答案 0 :(得分:14)

你可以这样做:

dir c:\codeishere -filter *.cs -recurse | select-string -Pattern '//.*;' | select Line,LineNumber,Filename

答案 1 :(得分:2)

gci c:\codeishere *.cs -r | select-string "//.*;"

尽管显示的文件名是相对路径,但select-string cmdlet已经完全符合您的要求。

答案 2 :(得分:2)

我会亲自走得更远。我想计算连续跟随行的数量。然后打印文件名,行数和行本身。您可以按行数(删除候选项?)对结果进行排序。 请注意,我的代码不计入注释行之间的空行,因此该部分被视为两个注释代码块:

// int a = 10;
// int b = 20;

// DoSomething()
// SomethingAgain()

这是我的代码。

$Location = "c:\codeishere"

$occurences = get-ChildItem $Location *cs -recurse | select-string '//.*;'
$grouped = $occurences | group FileName

function Compute([Microsoft.PowerShell.Commands.MatchInfo[]]$lines) {
  $local:lastLineNum = $null
  $local:lastLine = $null
  $local:blocks = @()
  $local:newBlock = $null
  $lines | 
    % { 
      if (!$lastLineNum) {                             # first line
        $lastLineNum = -2                              # some number so that the following if is $true (-2 and lower)
      }

      if ($_.LineNumber - $lastLineNum -gt 1) {        #new block of commented code
        if ($newBlock) { $blocks += $newBlock }
        $newBlock = $null
      }
      else {                                           # two consecutive lines of commented code
        if (!$newBlock) { 
          $newBlock = '' | select File,StartLine,CountOfLines,Lines
          $newBlock.File, $newBlock.StartLine, $newBlock.CountOfLines, $newBlock.Lines = $_.Filename,($_.LineNumber-1),2, @($lastLine,$_.Line)
        }
        else {
          $newBlock.CountOfLines += 1
          $newBlock.Lines += $_.Line
        }
      }
      $lastLineNum=$_.LineNumber
      $lastLine = $_.Line
    }

  if ($newBlock) { $blocks += $newBlock }
  $blocks
}

# foreach GroupInfo objects from group cmdlet
# get Group collection and compute 
$result = $grouped | % { Compute $_.Group }

#how to print
$result | % {
  write-host "`nFile $($_.File), line $($_.StartLine), count of lines: $($_.CountOfLines)" -foreground Green
  $_.Lines | % { write-host $_ }
}

# you may sort it by count of lines:
$result2 = $result | sort CountOfLines -desc
$result2 | % {
  write-host "`nFile $($_.File), line $($_.StartLine), count of lines: $($_.CountOfLines)" -foreground Green
  $_.Lines | % { write-host $_ }
}

如果您有任何想法如何改进代码,请发布!我有一种感觉,我可以使用一些标准cmdlet来完成它,代码可能会更短......

答案 3 :(得分:1)

我会考虑做类似的事情:

dir $location -inc *.cs -rec | `
  %{ $file = $_; $n = 0; get-content $_ } | `
  %{ $_.FileName = $file; $_.Line = ++$n; $_ } | `
  ?{ $_ -match $regex } | `
  %{ "{0}:{1}: {2}" -f ($_.FileName, $_.Line, $_)}

即。在字符串中添加额外的属性以指定文件名和行号,可以在正则表达式匹配后通过管道传递。

(使用ForEach-Object的-begin / -end脚本块应该能够简化这一点。)