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

时间:2010-04-22 06:01:24

标签: powershell colors

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

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

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

13 个答案:

答案 0 :(得分: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

答案 1 :(得分: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日):我已将写颜色更新为 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脚本带来了额外的检查和功能。

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

示例:

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

答案 3 :(得分: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提示符中使用它,或者只是将其添加到某些脚本中。

答案 4 :(得分:3)

这也有效......

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

答案 5 :(得分: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不会串联或组合文本,只是不会将光标移到下一行。

答案 6 :(得分: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

答案 7 :(得分: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源代码(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 }
    }
}

答案 8 :(得分: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 " "

答案 9 :(得分: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给了我这个奇妙的功能!!

答案 10 :(得分:0)

如果您处于我的情况,我从Microsoft文档中发现了一种简单的香草方式来设置控制台模式。因此,这是在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

注意: 我没有找到如何在VS Code的poswershell扩展中获得256种颜色的支持。

答案 11 :(得分: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;
}

答案 12 :(得分:0)

这是我想到的。希望它可以帮助某人。

$e = "$([char]27)"

enum ANSIFGColors {
  Black   = 30
  Red     = 91
  Green   = 92
  Yellow  = 93
  Blue    = 94
  Magenta = 95
  Cyan    = 96
  White   = 97
}

enum ANSIBGColors {
  Black   = 40
  Red     = 41
  Green   = 42
  Yellow  = 103
  Blue    = 44
  Magenta = 105
  Cyan    = 46
  White   = 107
}

function Colorize-Text {
  param (
    [string]$StringToColor,
    [ANSIFGColors]$TextColor,
    [ANSIBGColors]$BackgroundColor
  )

  $retValue = $null

  if ($BackgroundColor -ne $null ) { $retValue = [string]"$e[$($TextColor.value__);$($BackgroundColor.value__)m$StringToColor$e[0m" }
  else                             { $retValue = [string]"$e[$($TextColor.value__)m$StringToColor$e[0m" }

  return $retValue

}

可以这样使用;

$FirstVar = Colorize-Text -StringToColor "This is Green" -TextColor Green

$SecondVar = Colorize-Text -StringToColor "This is NOT Green" -TextColor Cyan -BackgroundColor Red

Write-host $FirstVar $SecondVar

或您选择的其他任何组合。