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

问题描述 投票:50回答:12

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

PS C:\> Write-Host "Red" -ForegroundColor Red
Red

此输出为红色。

PS C:\> Write-Host "Blue" -ForegroundColor Blue
Blue

此输出为蓝色。

PS C:\> Write-Host "Red", "Blue" -ForegroundColor Red, Blue
Red Blue

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

powershell colors
12个回答
34
投票

编辑(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

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

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

编辑(2018年4月9日):我已将Write-Color更新为v0.3。随意在我的site where I'm maintaining Write-Color上得到它。几乎没有什么微小变化。包含-NoNewLine和-ShowTime选项。

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

Josh的方法太棒了,我实际上为了我的需要而扩展了一点。我写了关于它的博客文章How to format PowerShell with Multiple Colors(有截图和所有 - 用于整个故事和用法)。

    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"

How to format PowerShell with Multiple Colors

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


0
投票

我试图在ISE下的Windows Server 2012R2盒子上运行它,而Jesse Chisholm的功能失败了,因为某些原因(Get-Host).UI.RawUII.ForegroundColor是-1。为了阻止这种情况发生并简化功能,我对其进行了如下修改:

function Write-ColorText
{
    # 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")

    $color = "Foreground"
    $nonewline = $false

    foreach($arg in $args)
    {
        if ($arg -eq "-nonewline")
        { 
            $nonewline = $true 
        }
        elseif ($allColors -contains $arg)
        {
            $color = $arg.substring(1)
        }
        else
        {
            if ($color -eq "Foreground")
            {
                Write-Host $arg -nonewline
            }
            else
            {
                Write-Host $arg -foreground $color -nonewline
            }
        }
    }

    Write-Host -nonewline:$nonewline
}

我知道这是一个老帖子,但希望这对某人有用,并感谢Jesse给了我这个奇妙的功能!!


0
投票

如果你在我的情况下,我已经从microsoft docs找到了一种普通的方式来设置控制台模式。所以这里有一个简单的方法来启动和结束cmd和powershell中的256色ansi控制台支持:

// https://docs.microsoft.com/en-us/windows/console/setconsolemode
#include <Windows.h>
#include <iostream>
struct  console_data {
    HANDLE hstdin;
    DWORD  mode;

    DWORD start()
    {
        hstdin = GetStdHandle(STD_OUTPUT_HANDLE);
        GetConsoleMode(hstdin, &mode);
        if (!SetConsoleMode(hstdin, mode | ENABLE_VIRTUAL_TERMINAL_PROCESSING)) {
            DWORD E = GetLastError();
            std::cout << " Error #" << E << "in:"  __FUNCTION__ "\n";
            return GetLastError();
        }
        std::cout << "\033[1;14mReady.\e[0m\n";
        return 0;
    }

    void end()
    {
        SetConsoleMode(hstdin, mode);
    }
    ~console_data() {
        end();
    }
    //...
}RTConsole;

//...
int main()
{
   //... 
   RTConsole.start();
   std::cout << "\033[38;5;192m Should be 'Orange'\n";
   RTConsole.end();
   return 0;
}

https://docs.microsoft.com/en-us/windows/console/setconsolemode

注意:我没有找到如何在VSCode powershell扩展中获得256色支持。


0
投票

这是一种简单的方法

if ($help)
{

    Write-Host "     For the switch " -NoNewline; Write-Host " -userUniqueId" -ForegroundColor Green -NoNewline; Write-Host ", enter an email address or samaccountname (pin) so '-userUniqueId 123456' "
    Write-Host "";
    Write-Host "     For the switch " -NoNewline; Write-Host " -disableMFAForUser" -ForegroundColor Green -NoNewline; Write-Host ", enter an email address or samaccountname (pin) with the -userUniqueId and then '-disableMFAForUser $true' "
    Write-Host "";
    Write-Host "     For the switch " -NoNewline; Write-Host "-enableMFAForUser" -ForegroundColor Green -NoNewline; Write-Host ", enter an email address or samaccountname (pin) with the -userUniqueId and then '-enableMFAForUser $true' "
    Write-Host "";
    Write-Host "     For the switch " -NoNewline; Write-Host "-verifyAllMFAEnabled" -ForegroundColor Green -NoNewline; Write-Host ", enter '-verifyAllMFAEnabled $true' "
    Write-Host "";
    Write-Host "     For the switch " -NoNewline; Write-Host " -verifyAllMFADisabledSpecificUser" -ForegroundColor Green -NoNewline; Write-Host ", enter an email address or samaccountname (pin) and then '-verifyAllMFADisabledSpecificUser $true' "
    Write-Host "";

    return;
}

51
投票

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

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

Write-Host "Red " -f red -nonewline; Write-Host "Blue " -f blue;

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

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

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

例子:

color-Write This is normal text
color-Write Normal -Red Red -White White -Blue Blue -ForeGround Normal

4
投票

这是一个小函数我写的输出彩色文本(它实际上更小,但我重写它更容易理解):

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;
}

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

例子:

`Write-Color "Hello, {red}my dear {green}friend !"` will output

Script screenshot

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


3
投票

这也有效......

Write-Host "Don't forget to " -ForegroundColor Yellow -NoNewline; Write-Host "CALL YOUR MOM " -ForegroundColor Red -NoNewline; Write-Host "every day!" -ForegroundColor Yellow

2
投票

我在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."

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


1
投票

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

Write-HostColored "I'm #green#green#, I'm #red#red#, and I'm #blue:white#blue on white#."

以上产量:

sample output

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

#<fgcolor>[:<bgcolor>]#<text>#

<fgcolor><bgcolor>必须是有效的[ConsoleColor]值,例如greenwhite(情况无关紧要)。跟随颜色规范直到下一个#,或隐含地直到字符串末尾的所有内容都以该颜色书写。


Write-HostColored source code (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 }
    }
}

1
投票

此代码具有不同数量的参数:Text,ForeGroundColor和BackGroundColor。

每个颜色列表都与旋转实现一起使用:

function Write-Color([String[]]$Text, [ConsoleColor[]]$ForeGroundColor, [ConsoleColor[]]$BackGroundColor) {
    for ($i = 0; $i -lt $Text.Length; $i++) {
        $Color = @{}
        if ($ForeGroundColor -and $BackGroundColor){
            $Color = @{
                ForegroundColor = $ForeGroundColor[$i%($ForeGroundColor.count)]
                BackgroundColor = $BackGroundColor[$i%($BackGroundColor.count)]
            }
        } elseif ($ForeGroundColor) {
            $Color = @{
                ForegroundColor = $ForeGroundColor[$i%($ForeGroundColor.count)]
            }
        } elseif ($BackGroundColor) {
            $Color = @{
                BackgroundColor = $BackGroundColor[$i%($BackGroundColor.count)]
            }
        }
        Write-Host $Text[$i] @color -NoNewLine
    }
    Write-Host
}

日志用法:

Write-Color "Check color list...".PadRight(50), '[', '   OK   ', ']' -fore cyan, White, green, white
Write-Color "Red Check is good...".PadRight(50), '[' ,' ERROR! ', ']' -fore cyan, White, red, white
Write-Color "Write-Color is cool !".PadRight(50), '[', '  WARN  ', ']' -fore cyan, White, Yellow, white

Enter image description here

列表用法(仅2个backGroundColor和4个foreGroundColor):

Write-Color (@(100..115) | %{" -> $_ : ".PadRight(30) + "`n"}) -ForeGroundColor cyan, yellow, magenta, red -BackGroundColor gray, black

Enter image description here

标准写主机

Write-Host (@(100..115) | %{" -> $_ : ".PadRight(30) + "`n"}) -BackgroundColor gray

Enter image description here


1
投票

稍微修改一下......我拿了版本2,删除了日志记录(因为我不想要它),然后添加了一个布尔参数,类似于写入主机的-NoNewLine。我特意尝试添加更改颜色的功能,并在同一行上提示用户输入,以便在用户未输入任何内容时突出显示默认答案。

我意识到这在Write-HostColored中可用(在之前的回答中)...但有时你只想要更简单的代码......

function Write-Color([String[]]$Text, [ConsoleColor[]]$Color = "White", [int]$StartTab = 0, [int] $LinesBefore = 0,[int] $LinesAfter = 0, [bool] $NewLine = $True) {

    # Notes:
    # - TimeFormat https://msdn.microsoft.com/en-us/library/8kb3ddd4.aspx
    #
    # Example:  Write-Color -Text "Red ", "Green ", "Yellow " -Color Red,Green,Yellow -NewLine $False
    #
    $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
        }
    }

    if ($NewLine -eq $False) {
        Write-Host -NoNewLine
    }
    else {
        Write-Host
    }

    if ($LinesAfter -ne 0) {
        for ($i = 0; $i -lt $LinesAfter; $i++) {
            Write-Host "`n"
        }
    }  # Add empty line after

}  # END FUNCTION Write-Color

我试图完成的样本:

Write-Color -Text "Is this correct? ","[y]","/n" -Color White, Magenta, White -NewLine $False ; Read-Host " "
© www.soinside.com 2019 - 2024. All rights reserved.