PowerShell 格式化 Cmdlet 输出

PowerShell Formatting Cmdlet Output

当我 运行 以下 Get-Command Get-ChildItem -Syntax 我得到:

<... empty line here ...>
Get-ChildItem [[-Path] <string[]>] [[-Filter] <string>] [-Include <string[]>] [-Exclude <string[]>] [-Recurse] [-Depth <uint32>] [-Force] [-Name] [-UseTransaction] [-Attributes <FlagsExpression[FileAttributes]>] [-Directory] [-File] [-Hidden] [-ReadOnly] [-System] [<CommonParameters>]
<... empty line here ...>
Get-ChildItem [[-Filter] <string>] -LiteralPath <string[]> [-Include <string[]>] [-Exclude <string[]>] [-Recurse] [-Depth <uint32>] [-Force] [-Name] [-UseTransaction] [-Attributes <FlagsExpression[FileAttributes]>] [-Directory] [-File] [-Hidden] [-ReadOnly] [-System] [<CommonParameters>]
<... empty line here ...>

然而,这不是我想要的格式化方式,我更愿意去除空行,并在每个语法行前加上 #(这样当换行时,很清楚在哪里每个语法定义开始)。这只是一个例子,想要对许多 Cmdlet 输出等做类似的事情,以便能够将输出操作为文本,上面、下面或中间没有空行,只有文本,格式化和紧凑,所以一般来说真的很感激如何以这种方式格式化。即

# Get-ChildItem [[-Path] <string[]>] [[-Filter] <string>] [-Include <string[]>] [-Exclude <string[]>] [-Recurse] [-Depth <uint32>] [-Force] [-Name] [-UseTransaction] [-Attributes <FlagsExpression[FileAttributes]>] [-Directory] [-File] [-Hidden] [-ReadOnly] [-System] [<CommonParameters>]
# Get-ChildItem [[-Filter] <string>] -LiteralPath <string[]> [-Include <string[]>] [-Exclude <string[]>] [-Recurse] [-Depth <uint32>] [-Force] [-Name] [-UseTransaction] [-Attributes <FlagsExpression[FileAttributes]>] [-Directory] [-File] [-Hidden] [-ReadOnly] [-System] [<CommonParameters>]

谁能建议一种简单的方法来实现这样的格式化输出?

给你!

(Get-Command Get-ChildItem -Syntax) -split '\r\n' |
    where {$_} | foreach {"# $_"}

# Get-ChildItem [[-Path] <string[]>] [[-Filter] <string>] [-Include <string[]>] [-Exclude <string[]>] [-Recurse] [-Depth <uint32>] [-Force] [-Name] [-UseTransaction] [-Attributes <FlagsExpression[FileAttributes]>] [-Directory] [-File] [-Hidden] [-ReadOnly] [-System] [<CommonParameters>]
# Get-ChildItem [[-Filter] <string>] -LiteralPath <string[]> [-Include <string[]>] [-Exclude <string[]>] [-Recurse] [-Depth <uint32>] [-Force] [-Name] [-UseTransaction] [-Attributes <FlagsExpression[FileAttributes]>] [-Directory] [-File] [-Hidden] [-ReadOnly] [-System] [<CommonParameters>]

您将受到控制台最大宽度的限制,因此即使它们是一行,它也会换行。如果您想将其粘贴到其他内容,您可以通过管道输入 clip

(Get-Command Get-ChildItem -Syntax) -split '\r\n' |
    where {$_} | foreach {"# $_"} | clip

太棒了,谢谢道格,真的很有用。我还使用了一个小函数来帮助我很好地格式化 line-wraps,这样我就可以使用你的代码来绕过最大宽度:

(Get-Command Get-ChildItem -Syntax) -split '\r\n' | where {$_} | foreach {"# $_"} | Write-Wrap

其中 Write-Wrap 函数始终清晰地格式化为控制台的宽度(使用下面的 mklment0 点和他指出的基本 PROCESS 块进行编辑):

function Write-Wrap {
    [CmdletBinding()]Param( [parameter(Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName)] [Object[]]$chunk )
    PROCESS {
        $Lines = @()
        foreach ($line in $chunk) {
            $str = ''; $counter = 0
            $line -split '\s+' | % {
                $counter += $_.Length + 1
                if ($counter -gt $Host.UI.RawUI.BufferSize.Width) {
                    $Lines += ,$str.trim()
                    $str = ''
                    $counter = $_.Length + 1
                }
                $str = "$str$_ "
            }
            $Lines += ,$str.trim()
        }
        $Lines
    }
}

这是我目前的用途。我发现导航模块很尴尬,并且想要一种 better/faster 的方式来获得紧凑的概述。我将这些保存在我的个人 Custom-Tools.psm1 模块中,它可以帮助我快速查看系统中的内容。

键入 mods 以查看所有已安装的模块及其所在位置。

键入 mods <partial_name> 以查看所有匹配项。例如mods micmods soft

键入 mod <module-name> 以快速查看给定模块内容的详细信息。

键入 mod <module-name> -i | more 以获取有关该模块内容的所有语法详细信息。

我发现这是一种查询模块的非常快捷方便的方法。希望对某些人有用。

mods

function mods ($search) {
    ""
    ":: Complete `$env:PSModulePath string:`n"
    $env:PSModulePath
    $env:PSModulePath -Split ";" -replace "\+$", "" | sort
    ""
    ""
    $PathArray = $env:PSModulePath -Split ";" -replace "\+$", "" | sort
    ""
    foreach ($Path in $PathArray) {
        if ($Path -ne '') {
            $Path = $Path.TrimEnd('\')
            echo ":: Modules under '$Path':`n"
            # if (Test-Path $Path) {
            $temp = (dir "$Path\*$search*" -Directory -EA Silent | Select -ExpandProperty Name) -join ", "   # mods w*  => mods w** which resolves fine
            if ($temp -eq "") { "No matches for '$search' exist in this path" }
            # } else { "This path is in `$env:PSModulePath but the folder does not exist"}
            Write-Wrap $temp
            ""
        }
    }
    ""
}

mod

function mod ($Module, $def, [switch]$ShowModulesHere, [switch]$Info) {
    if ($null -eq $Module) { "You must specify a Module to examine. Run 'mods' to see available Modules." ; break }
    ""
    if ([bool](Get-Module $Module -ListAvailable) -eq $true) {
        if ([bool](Get-Module $Module) -eq $true) { ":: Module '$Module' is already imported, so all functions are available`n" }
        else { ":: Module '$Module' was not imported, running import now ..." ; Import-Module $Module }
    }
    else { "Could not find Module in available Module folders`n" ; break }
    
    $ModulePath = ((Get-Module $Module | select Path).Path).TrimEnd('\')
    $ModuleVer = (Get-Module $Module -ListAvailable | select Version).Version | sls "\d"
    ":: '$Module' is version $($ModuleVer)`n`n$ModulePath"
    
    $ModuleRoot = Split-Path ((Get-Module $Module | select Path).Path).TrimEnd("\")
    $ModulesHere = (dir $Path -Directory | Select -ExpandProperty Name) -join ", "
    
    if ($Info) {
        ""
        foreach ($i in (Get-Command -Module $Module).Name) { 
            $out = $i   # Parse the info string from after the "{" 
            $type = "" ; try { $type = ((gcm $i -EA silent).CommandType); } catch { $deferr = 1 }
            $out += "   # $type"
            $syntax = Get-Command $i -Syntax
            $definition = "" ; if ($type -eq "Alias") { $definition = (get-alias $i).Definition }
            $syntax = $syntax -replace $definition, ""
            if ($type -eq "Alias") { $out += " for '$definition'" }
            $out
            if ($type -eq "Function") { $syntax = $syntax -replace $i, "" }
            if ($type -eq "Cmdlet") { $syntax = $syntax -replace $i, "" }
            if (!([string]::IsNullOrWhiteSpace($syntax))) { 
                $syntax -split '\r\n' | where {$_} | foreach { "Syntax =>   $_" | Write-Wrap }
            }
            ""
        }
        ""
    }
    else {
        ""
        ":: Module functions:"
        $out = ""; foreach ($i in (Get-Command -Module $Module).Name) { $out += " $i," } ; "" ; Write-Wrap $out.TrimEnd(", ")
        ""
    }
    $ModPaths = $env:PSModulePath -Split ";" -replace "\+$", "" | sort
    ":: Module Paths (`$env:PSModulePath):"
    foreach ($i in $ModPaths) { "   $i"}
    ""
    ":: '$Module' Path:`n`n   $ModulePath"
    ""
    foreach ($i in $ModPaths) {
        if (!([string]::IsNullOrWhiteSpace($i))) {
           if ($ModulePath | sls $i -SimpleMatch) { $ModRoot = $i ; ":: `$env:PSModulePath parent location is:`n`n   $i" }
        }
    }
    ""

    if ($def -ne $null) {
        ":: Press any key to open '$def' definition:"
        pause
        ""
        def $def
        ""
    }

    if ($ShowModulesHere -eq $true) {
        ":: This `$env:PSModulePath root also contains the following Modules:"
        ""
        (dir $ModRoot -Directory | Select -ExpandProperty Name) -join ", "
        ""
    }
}