在PowerShell中对Select-String的输出进行对齐

3

当我使用 select-string 时,我几乎总是希望我的输出对齐,即文件名、行号和找到的文本应该都对齐成列。视觉上更不容易分散注意力,通常可以更容易地发现差异。作为一个微不足道的例子,我在这里在文件中间注入了一个额外的空格:

PS> Get-ChildItem *.cs | Select-StringAligned -pattern override
---
FileWithQuiteALengthyName.cs  : 34:    protected override void Foo()
ShortName.cs                  : 46:    protected override void  Bar()
MediumNameFileHere.cs         :123:    protected override void Baz()
---

不幸的是,Select-String 不能做到这一点。 实际上,它会给出以下结果 - 你能发现这里多了一个空格吗?

PS> Get-ChildItem *.cs | Select-String -pattern override
---
FileWithQuiteALengthyName.cs:34:    protected override void Foo()
ShortName.cs:46:    protected override void  Bar()
MediumNameFileHere.cs:123:    protected override void Baz()
---

有没有办法强制Select-String对齐其输出列?

编辑: 哎呀!我忘记了一个重要的部分:如果可能,我还想包括-Context参数,这样就可以获取匹配项之前和之后的任意行。

3个回答

7
使用对象:
Get-ChildItem *.cs | select-string -pattern override |
select Filename,LineNumber,Line | Format-Table -AutoSize

"并且如果您决定要保留它,它也适合导出为csv格式。将使用上下文的要求添加到其中会使事情变得更加复杂。"
function ssalign {
begin {$display = @()}
process {
 $_  -split "`n" |
 foreach {
   $display += 
   $_ | New-PSObjectFromMatches -Pattern '^(.+)?:([\d]+):(.+)' -Property $null,File,Line,Text 
  } 
}
end {
$display | 
 foreach {$_.line = ':{0,5}:' -f $_.line}
 $display | ft -AutoSize -HideTableHeaders
 }
}

Get-ChildItem *.cs | Select-StringAligned -pattern override | ssalign

在此获取New-PSObjectFromMatches函数: http://gallery.technet.microsoft.com/scriptcenter/New-PSObjectFromMatches-87d8ce87

兄弟,太棒了。谢谢你。 - Kellen Stuart

4

this maybe:

Get-ChildItem *.cs | select-string -pattern override | ft filename, linenumber , line -AutoSize

或者像这样:
Get-ChildItem *.cs | select-string -pattern override |
 % { "{0,-20}{1,15}{2,70}" -f $_.filename, $_.linenumber , $_.line }

字符串格式中的第一部分值 -f ("{0,-20}{1,15}{2,70}") 必须根据您的匹配长度进行检查。


你对我在你回答后增加的要求有什么想法吗?(我的错:-() - Michael Sorens

1
我向 @mjolinor 发放勾号,以表彰他提供的优秀代码和所付出的努力。尽管如此,一些读者可能会对这个变化感兴趣,特别是针对名称宽度和数字宽度参数的格式灵活性提供:

filter Select-StringAligned
{
    [CmdletBinding()]
    Param (
    [Parameter(Mandatory=$true,Position=0, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)]
    [string[]]$InputObject,

    [Parameter(Mandatory=$true,Position=1)]
    [string]$Pattern,
    [int[]]$Context = @(0),
    [int]$NameWidth = 35,
    [int]$NumberWidth = 4)

    select-string -Path $InputObject -Pattern $pattern -Context $Context |
    % {
        $entry = $_            

        if ($Context[0] -eq 0) { $offset = 0 }
        else { $offset = @($entry.Context.PreContext).Count }
        $linenum = $entry.LineNumber - $offset - 1

        # For some reason need to special case the $list construction; otherwise acts like Context=(1,1)
        if ($Context[0] + $Context[1] -eq 0) {
            $list = $entry.Line
        }
        else {
            $list =  @($entry.Context.PreContext)
            $list += $entry.Line
            $list += $entry.Context.PostContext
        }
        $list | % { 
            if ($entry.FileName.length -lt $nameWidth) { $truncatedName = $entry.FileName }
            else { $truncatedName=$entry.FileName.SubString(0,$NameWidth) }
            "{0,-$NameWidth}:{1,$NumberWidth}: {2}" -f $truncatedName, $linenum++, $_
        }
    }
}

这里是一个使用示例。-NameWidth参数允许字段宽度小于(截断)或大于(填充)文件名。
$pattern = "public"
Get-ChildItem *.cs |
Select-StringAligned -pattern $pattern -Context 0,2 -NameWidth 20 -NumberWidth 3

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接