PowerShell中的多个前景色在一个命令中

Mar*_*lin 51 powershell colors

我想用一个语句输出许多不同的前景色.

PS C:\> Write-Host "Red" -ForegroundColor Red
Red
Run Code Online (Sandbox Code Playgroud)

此输出为红色.

PS C:\> Write-Host "Blue" -ForegroundColor Blue
Blue
Run Code Online (Sandbox Code Playgroud)

此输出为蓝色.

PS C:\> Write-Host "Red", "Blue" -ForegroundColor Red, Blue
Red Blue
Run Code Online (Sandbox Code Playgroud)

这个输出是洋红色的,但我希望红色这个词的颜色是红色,而通过一个命令我想要蓝色代表蓝色.我怎样才能做到这一点?

Jos*_*osh 51

您可以滚动自己的Write-Color命令或查找更改颜色的内联标记的内容.这就是ANSI转义序列在BBS时代的工作方式.

但是你可以做到你想做的事情:

Write-Host "Red " -f red -nonewline; Write-Host "Blue " -f blue;
Run Code Online (Sandbox Code Playgroud)

这是一个简单的小功能,可以满足您的要求.

function Write-Color([String[]]$Text, [ConsoleColor[]]$Color) {
    for ($i = 0; $i -lt $Text.Length; $i++) {
        Write-Host $Text[$i] -Foreground $Color[$i] -NoNewLine
    }
    Write-Host
}

Write-Color -Text Red,White,Blue -Color Red,White,Blue
Run Code Online (Sandbox Code Playgroud)

  • 不幸的是,PowerShell仅支持16个基本的ConsoleColor枚举值.黑色DarkBlue DarkGreen DarkCyan DarkRed DarkMagenta DarkYellow灰色DarkGray蓝色绿色青色红色洋红色黄色白色 (5认同)
  • 您可以将-nonewline缩短为-n,并将颜色名称缩短为可解析的最短前缀:-`Write-Host“ Red” -fr -n; 写主机“ Blue” -f Blu -n; 写主机“ Cyan” -f C` (2认同)

Mad*_*Boy 36

编辑(2018年5月7日):我已将Write-Color更新为0.5并将其作为模块发布.此外,代码现已发布在github上.

0.5的变化:

  • 添加了backgroundcolor
  • 将别名T/B/C添加到更短的代码中
  • 添加别名功能(可与"WC"一起使用)
  • 修复了模块发布

变化0.4

  • 解决了小问题
  • 作为模块发布

资源链接:

感谢已发布的模块,您可以轻松使用以下代码:

Install-Module PSWriteColor
Write-Color -Text "Some","Text" -Color Yellow,Red
Run Code Online (Sandbox Code Playgroud)

不再需要复制/粘贴代码.请享用.

旧代码如下.强烈建议使用上面的链接获取最新代码:

编辑(2018年4月9日):我已将Write-Color更新为v0.3.随意在我保持Write-Color的网站上获取它.几乎没有什么微小变化.包含 - NoNewLine和 - ShowTime选项.

编辑(2017年6月):使用新版本更新,添加日志记录到文件以进行日志记录

Josh的方法太棒了,我实际上为了我的需要而扩展了一点.我写了博客文章如何使用多种颜色格式化PowerShell(截图和所有 - 用于整个故事和用法).

    function Write-Color([String[]]$Text, [ConsoleColor[]]$Color = "White", [int]$StartTab = 0, [int] $LinesBefore = 0,[int] $LinesAfter = 0, [string] $LogFile = "", $TimeFormat = "yyyy-MM-dd HH:mm:ss") {
    # version 0.2
    # - added logging to file
    # version 0.1
    # - first draft
    # 
    # Notes:
    # - TimeFormat https://msdn.microsoft.com/en-us/library/8kb3ddd4.aspx

    $DefaultColor = $Color[0]
    if ($LinesBefore -ne 0) {  for ($i = 0; $i -lt $LinesBefore; $i++) { Write-Host "`n" -NoNewline } } # Add empty line before
    if ($StartTab -ne 0) {  for ($i = 0; $i -lt $StartTab; $i++) { Write-Host "`t" -NoNewLine } }  # Add TABS before text
    if ($Color.Count -ge $Text.Count) {
        for ($i = 0; $i -lt $Text.Length; $i++) { Write-Host $Text[$i] -ForegroundColor $Color[$i] -NoNewLine } 
    } else {
        for ($i = 0; $i -lt $Color.Length ; $i++) { Write-Host $Text[$i] -ForegroundColor $Color[$i] -NoNewLine }
        for ($i = $Color.Length; $i -lt $Text.Length; $i++) { Write-Host $Text[$i] -ForegroundColor $DefaultColor -NoNewLine }
    }
    Write-Host
    if ($LinesAfter -ne 0) {  for ($i = 0; $i -lt $LinesAfter; $i++) { Write-Host "`n" } }  # Add empty line after
    if ($LogFile -ne "") {
        $TextToFile = ""
        for ($i = 0; $i -lt $Text.Length; $i++) {
            $TextToFile += $Text[$i]
        }
        Write-Output "[$([datetime]::Now.ToString($TimeFormat))]$TextToFile" | Out-File $LogFile -Encoding unicode -Append
    }
}


Write-Color -Text "Red ", "Green ", "Yellow " -Color Red,Green,Yellow

Write-Color -Text "This is text in Green ",
                   "followed by red ",
                   "and then we have Magenta... ",
                   "isn't it fun? ",
                   "Here goes DarkCyan" -Color Green,Red,Magenta,White,DarkCyan

Write-Color -Text "This is text in Green ",
                   "followed by red ",
                   "and then we have Magenta... ",
                   "isn't it fun? ",
                   "Here goes DarkCyan" -Color Green,Red,Magenta,White,DarkCyan -StartTab 3 -LinesBefore 1 -LinesAfter 1

Write-Color "1. ", "Option 1" -Color Yellow, Green
Write-Color "2. ", "Option 2" -Color Yellow, Green
Write-Color "3. ", "Option 3" -Color Yellow, Green
Write-Color "4. ", "Option 4" -Color Yellow, Green
Write-Color "9. ", "Press 9 to exit" -Color Yellow, Gray -LinesBefore 1



Write-Color -LinesBefore 2 -Text "This little ","message is ", "written to log ", "file as well." -Color Yellow, White, Green, Red, Red -LogFile "C:\testing.txt" -TimeFormat "yyyy-MM-dd HH:mm:ss"
Write-Color -Text "This can get ","handy if ", "want to display things, and log actions to file ", "at the same time." -Color Yellow, White, Green, Red, Red -LogFile "C:\testing.txt"
Run Code Online (Sandbox Code Playgroud)

如何使用多种颜色格式化PowerShell

它实际上带来了对Josh脚本的额外检查和功能.

  • 5年前问过这个问题,现在得到了回答。非常好!帽子提示@Josh 协助。 (2认同)

小智 5

这个函数提供不同的语法糖:

function color-Write
{
    # DO NOT SPECIFY param(...)
    #    we parse colors ourselves.

    $allColors = ("-Black",   "-DarkBlue","-DarkGreen","-DarkCyan","-DarkRed","-DarkMagenta","-DarkYellow","-Gray",
                  "-Darkgray","-Blue",    "-Green",    "-Cyan",    "-Red",    "-Magenta",    "-Yellow",    "-White")
    $foreground = (Get-Host).UI.RawUI.ForegroundColor # current foreground
    $color = $foreground
    [bool]$nonewline = $false
    $sofar = ""
    $total = ""

    foreach($arg in $args)
    {
        if ($arg -eq "-nonewline") { $nonewline = $true }
        elseif ($arg -eq "-foreground")
        {
            if ($sofar) { Write-Host $sofar -foreground $color -nonewline }
            $color = $foregrnd
            $sofar = ""
        }
        elseif ($allColors -contains $arg)
        {
            if ($sofar) { Write-Host $sofar -foreground $color -nonewline }
            $color = $arg.substring(1)
            $sofar = ""
        }
        else
        {
            $sofar += "$arg "
            $total += "$arg "
        }
    }
    # last bit done special
    if (!$nonewline)
    {
        Write-Host $sofar -foreground $color
    }
    elseif($sofar)
    {
        Write-Host $sofar -foreground $color -nonewline
    }
}
Run Code Online (Sandbox Code Playgroud)

例子:

color-Write This is normal text
color-Write Normal -Red Red -White White -Blue Blue -ForeGround Normal
Run Code Online (Sandbox Code Playgroud)

  • 虽然这个函数很有趣,但它的名字并不反映powershell命名约定:`Verb-Subject`.检查[Windows PowerShell的已批准的Versbs](http://msdn.microsoft.com/library/ms714428.aspx)以检查标准谓词. (2认同)

小智 5

这是我编写的用于输出彩色文本的小函数(它实际上更小,但我重写了它以使其更容易理解):

function Write-Color() {
    Param (
        [string] $text = $(Write-Error "You must specify some text"),
        [switch] $NoNewLine = $false
    )

    $startColor = $host.UI.RawUI.ForegroundColor;

    $text.Split( [char]"{", [char]"}" ) | ForEach-Object { $i = 0; } {
        if ($i % 2 -eq 0) {
            Write-Host $_ -NoNewline;
        } else {
            if ($_ -in [enum]::GetNames("ConsoleColor")) {
                $host.UI.RawUI.ForegroundColor = ($_ -as [System.ConsoleColor]);
            }
        }

        $i++;
    }

    if (!$NoNewLine) {
        Write-Host;
    }
    $host.UI.RawUI.ForegroundColor = $startColor;
}
Run Code Online (Sandbox Code Playgroud)

使用起来非常简单:只需Write-Color "your text"在您希望文本着色的大括号之间使用并添加一些颜色名称即可。

例子:

`Write-Color "Hello, {red}my dear {green}friend !"` will output
Run Code Online (Sandbox Code Playgroud)

脚本截图

您可以将其放入$profile文件中以在简单的 PowerShell 提示符中使用它,或者只是将其添加到某些脚本中。


mkl*_*nt0 5

找到下面的高级函数Write-HostColored,它允许在字符串中嵌入着色指令,包括前景色和背景色:

Write-HostColored "I'm #green#green#, I'm #red#red#, and I'm #blue:white#blue on white#."
Run Code Online (Sandbox Code Playgroud)

上面的结果是:

样本输出

除了使用 和 接受默认的前景色和背景色之外-ForegroundColor-BackgroundColor您还可以使用以下语法在要写入的字符串中嵌入一种或多种颜色规范:

#<fgcolor>[:<bgcolor>]#<text>#
Run Code Online (Sandbox Code Playgroud)

<fgcolor>并且<bgcolor>必须是有效值[ConsoleColor],例如greenor white(不区分大小写)。颜色规范之后直到下一个#或隐式直到字符串末尾的所有内容都以该颜色编写。


Write-HostColored源代码(PSv2+):

<#
.SYNOPSIS
A wrapper around Write-Host that supports selective coloring of
substrings via embedded coloring specifications.

.DESCRIPTION
In addition to accepting a default foreground and background color,
you can embed one or more color specifications in the string to write,
using the following syntax:
#<fgcolor>[:<bgcolor>]#<text>#

<fgcolor> and <bgcolor> must be valid [ConsoleColor] values, such as 'green' or 'white' (case does not matter).
Everything following the color specification up to the next '#', or impliclitly to the end of the string,
is written in that color.

Note that nesting of color specifications is not supported.
As a corollary, any token that immediately follows a color specification is treated
as text to write, even if it happens to be a technically valid color spec too.
This allows you to use, e.g., 'The next word is #green#green#.', without fear
of having the second '#green' be interpreted as a color specification as well.

.PARAMETER ForegroundColor
Specifies the default text color for all text portions
for which no embedded foreground color is specified.

.PARAMETER BackgroundColor
Specifies the default background color for all text portions
for which no embedded background color is specified.

.PARAMETER NoNewline
Output the specified string withpout a trailing newline.

.NOTES
While this function is convenient, it will be slow with many embedded colors, because,
behind the scenes, Write-Host must be called for every colored span.

.EXAMPLE
Write-HostColored "#green#Green foreground.# Default colors. #blue:white#Blue on white."

.EXAMPLE
'#black#Black on white (by default).#Blue# Blue on white.' | Write-HostColored -BackgroundColor White

#>
function Write-HostColored() {
    [CmdletBinding()]
    param(
        [parameter(Position=0, ValueFromPipeline=$true)]
        [string[]] $Text
        ,
        [switch] $NoNewline
        ,
        [ConsoleColor] $BackgroundColor = $host.UI.RawUI.BackgroundColor
        ,
        [ConsoleColor] $ForegroundColor = $host.UI.RawUI.ForegroundColor
    )

    begin {
        # If text was given as a parameter value, it'll be an array.
        # Like Write-Host, we flatten the array into a single string
        # using simple string interpolation (which defaults to separating elements with a space,
        # which can be changed by setting $OFS).
        if ($Text -ne $null) {
            $Text = "$Text"
        }
    }

    process {
        if ($Text) {

            # Start with the foreground and background color specified via
            # -ForegroundColor / -BackgroundColor, or the current defaults.
            $curFgColor = $ForegroundColor
            $curBgColor = $BackgroundColor

            # Split message into tokens by '#'.
            # A token between to '#' instances is either the name of a color or text to write (in the color set by the previous token).
            $tokens = $Text.split("#")

            # Iterate over tokens.
            $prevWasColorSpec = $false
            foreach($token in $tokens) {

                if (-not $prevWasColorSpec -and $token -match '^([a-z]*)(:([a-z]+))?$') { # a potential color spec.
                    # If a token is a color spec, set the color for the next token to write.
                    # Color spec can be a foreground color only (e.g., 'green'), or a foreground-background color pair (e.g., 'green:white'), or just a background color (e.g., ':white')
                    try {
                        $curFgColor = [ConsoleColor] $matches[1]
                        $prevWasColorSpec = $true
                    } catch {}
                    if ($matches[3]) {
                        try {
                            $curBgColor = [ConsoleColor] $matches[3]
                            $prevWasColorSpec = $true
                        } catch {}
                    }
                    if ($prevWasColorSpec) {
                        continue
                    }
                }

                $prevWasColorSpec = $false

                if ($token) {
                    # A text token: write with (with no trailing line break).
                    # !! In the ISE - as opposed to a regular PowerShell console window,
                    # !! $host.UI.RawUI.ForegroundColor and $host.UI.RawUI.ForegroundColor inexcplicably
                    # !! report value -1, which causes an error when passed to Write-Host.
                    # !! Thus, we only specify the -ForegroundColor and -BackgroundColor parameters
                    # !! for values other than -1.
                    # !! Similarly, PowerShell Core terminal windows on *Unix* report -1 too.
                    $argsHash = @{}
                    if ([int] $curFgColor -ne -1) { $argsHash += @{ 'ForegroundColor' = $curFgColor } }
                    if ([int] $curBgColor -ne -1) { $argsHash += @{ 'BackgroundColor' = $curBgColor } }
                    Write-Host -NoNewline @argsHash $token
                }

                # Revert to default colors.
                $curFgColor = $ForegroundColor
                $curBgColor = $BackgroundColor

            }
        }
        # Terminate with a newline, unless suppressed
        if (-not $NoNewLine) { write-host }
    }
}
Run Code Online (Sandbox Code Playgroud)


小智 5

我在https://blogs.technet.microsoft.com/heyscriptingguy/2011/05/17/writing-output-with-powershell/找到了一个更简单的选择

基本上,第一个写入主机包括选项 -NoNewLine。这可以防止形成新线。下一个写入主机将立即添加到前一个文本之后。每个单独的写主机都可以有 -foregroundcolor 选项。可以针对您需要的每种颜色更改重复此操作。

一行三种颜色的文本示例:

write-host "Your text here " -ForeGroundColor Red -NoNewLine
write-host "some other text here " -ForeGroundColor Yellow -NoNewLine
write-host "And the last text here."
Run Code Online (Sandbox Code Playgroud)

请注意,第一个和第二个写入主机中的文本后面有一个空格。PowerShell 不会连接或组合文本,它只是不会将光标移动到下一行。