Regex 使用Powershell打印与正则表达式匹配的代码行号
我认为我们的源代码中有一堆注释掉的代码,我们没有立即删除它,而是把它留下了。现在我想做一些清理工作 因此,假设我有一个足够好的正则表达式来查找注释(下面的正则表达式很简单,我可以根据我们的编码标准对其进行扩展),我如何获取我读取的文件的结果并输出以下内容:Regex 使用Powershell打印与正则表达式匹配的代码行号,regex,powershell,comments,Regex,Powershell,Comments,我认为我们的源代码中有一堆注释掉的代码,我们没有立即删除它,而是把它留下了。现在我想做一些清理工作 因此,假设我有一个足够好的正则表达式来查找注释(下面的正则表达式很简单,我可以根据我们的编码标准对其进行扩展),我如何获取我读取的文件的结果并输出以下内容: 文件名 行号 实际的代码行 我想我已经有了答案的基础,但我不知道如何把我读过的文件用正则表达式解析出来,然后以这种格式输出 我不是在寻找完美的解决方案——我只是想找到大块注释掉的代码。通过查看结果并看到一堆具有相同名称和顺序行号的文件,我
- 文件名
- 行号
- 实际的代码行
$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?
}
我会考虑这样做:
dir $location -inc *.cs -rec | `
%{ $file = $_; $n = 0; get-content $_ } | `
%{ $_.FileName = $file; $_.Line = ++$n; $_ } | `
?{ $_ -match $regex } | `
%{ "{0}:{1}: {2}" -f ($_.FileName, $_.Line, $_)}
也就是说,在字符串中添加额外的属性,以指定文件名和行号,在正则表达式匹配后可以通过管道进行传输
(使用每个对象的-begin/-end脚本块应该可以简化此过程。)您可以执行以下操作:
dir c:\codeishere -filter *.cs -recurse | select-string -Pattern '//.*;' | select Line,LineNumber,Filename
select-string
cmdlet已经完全满足了您的要求,尽管显示的文件名是一个相对路径。我个人会更进一步。我想计算以下连续行的数量。然后打印文件名、行数和行本身。您可以按行数对结果进行排序(是否删除候选行?)。
请注意,我的代码不计算注释行之间的空行数,因此此部分被视为两个注释代码块:
// 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来完成,代码可以更短。我不确定{$\u.\u-match$regex}| `在做什么,但这一行似乎阻止了我获得结果。那有什么用?此外,我还必须将$FileName和$Line更改为$FileName和$Line,才能将其保存到run@Macho字体输入。。。will ix,应该是$\注意其他答案:select string已经捕获了文件名和行号。这超出了问题的范围,但是哇。。。这太棒了。谢谢我将使用这个。是的,超出范围,但我认为它可能有用。除此之外,这很有趣:)如果您对匹配块之间的空行也感兴趣,请告诉我。我会尝试调整脚本。有没有办法将
LineNumber
的实际整数存储到变量中,而不使用文本LineNumber\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
$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 $_ }
}