【问题标题】:Use Powershell to print out line number of code matching a RegEx使用 Powershell 打印出与 RegEx 匹配的代码行号
【发布时间】:2010-11-01 14:17:22
【问题描述】:

我认为我们的源代码中有一堆注释掉的代码,我们没有立即删除它,而是将其保留。现在我想做一些清理工作。

所以假设我有足够好的正则表达式来查找 cmets(下面的正则表达式很简单,我可以根据我们的编码标准对其进行扩展),我如何获取我读取的文件的结果并输出以下:

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

我想我在这里有了答案的基础,但是我不知道如何获取我已经阅读并使用 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?
}

【问题讨论】:

    标签: regex powershell comments


    【解决方案1】:

    你可以这样做:

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

    【讨论】:

    • 我有什么办法可以将LineNumber 的实际整数存储到一个变量中而不需要文本LineNumber ________ etc
    【解决方案2】:
    gci c:\codeishere *.cs -r | select-string "//.*;"
    

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

    【讨论】:

      【解决方案3】:

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

      // 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 来做到这一点,而且代码可以更短..

      【讨论】:

      • 这超出了问题的范围,但是哇......这太棒了。谢谢!!!!我会用这个。
      • 是的,超出了范围,但我认为它可能有用。除此之外它很有趣 :) 如果您也有兴趣匹配块之间的空行,请告诉我。我会尝试调整脚本。
      【解决方案4】:

      我会考虑做类似的事情:

      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 脚本块应该可以简化这一点。)

      【讨论】:

      • 我不确定是什么?{ $_._ -match $regex } | ` 正在做,但这似乎阻止我得到结果。那有什么作用?另外,我必须将 $_.FileName 和 $_.Line 更改为 $FileName 和 $Line 才能运行
      • @Macho:错别字...将 ix,应该只是 $_。
      • 注意其他答案:select-string 已经捕获了文件名和行号。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-01-06
      • 1970-01-01
      • 1970-01-01
      • 2021-05-25
      • 2017-05-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多