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参数,以便可以在比赛前后获得任意数量的行。

4

3 回答 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

于 2013-03-16T02:17:46.333 回答
4

这可能是:

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}”)

于 2013-03-15T22:49:52.497 回答
1

我正在给@mjolinor 打勾,因为他提供了一段不错的代码以及他付出的努力。尽管如此,一些读者可能会对这种变化感兴趣,特别是我为格式灵活性提供的 NameWidth 和 NumberWidth 参数:

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
于 2013-03-27T07:24:35.493 回答