Multiple foreground colors in PowerShell in one command

后端 未结 13 1744
难免孤独
难免孤独 2020-11-28 07:19

I want to output many different foreground colors with one statement.

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

This output i

相关标签:
13条回答
  • 2020-11-28 07:57

    This code is available with a different number of arguments: Text, ForeGroundColor, and BackGroundColor.

    Each colorlist is used with a rotate implementation:

    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
    }
    

    Log usage:

    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
    

    List Usage (just 2 backGroundColor and 4 foreGroundColor):

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

    Standard Write-Host

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

    0 讨论(0)
  • 2020-11-28 08:00

    Edit (7th May 2018): I've updated Write-Color to 0.5 and published it as module. Also code is now published on github.

    Changes in 0.5:

    • added backgroundcolor
    • added aliases T/B/C to shorter code
    • added alias to function (can be used with “WC”)
    • fixes to module publishing

    Changes in 0.4

    • fixed small issues
    • published as module

    Links to resources:

    • GitHub Repository
    • GitHub Reporting Issues
    • PowerShellGallery Module
    • Module description and a starting point.

    Thanks to published module you can easily use the code as below:

    Install-Module PSWriteColor
    Write-Color -Text "Some","Text" -Color Yellow,Red
    

    There is no more need to copy/paste code. Enjoy.

    Old code is below. It's highly advised to use links above for newest code:

    Edit (9th April 2018): I've updated Write-Color to v0.3. Feel free to get it at my site where I'm maintaining Write-Color. There are few small changes. Inluded -NoNewLine and -ShowTime option.

    Edit (Jun 2017): updated with new version, added logging to file for logging purposes

    Josh method was so great that I actually went and expanded it a bit for my needs. I've written blog post How to format PowerShell with Multiple Colors about it (with screenshots and all - for the whole story and usage).

        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/8kb3ffffd4.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"
    

    It actually brings additional checks and features over Josh script.

    0 讨论(0)
  • 2020-11-28 08:01

    Slight modification to this one... I took version 2, removed the logging (because I don't want it), and then added a Boolean parameter, similar to -NoNewLine for Write-Host. I was specifically trying to add the ability to change the colors and prompt for user input on the same line so that I could highlight the default answer if the user does not enter anything.

    I realize this was available in Write-HostColored (in a previous answer)... but sometimes you just want simpler code...

    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/8kb3ffffd4.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
    

    Sample of what I was trying to accomplish:

    Write-Color -Text "Is this correct? ","[y]","/n" -Color White, Magenta, White -NewLine $False ; Read-Host " "
    
    0 讨论(0)
  • 2020-11-28 08:02

    You could roll your own Write-Color command or something that looks for inline tokens that change the color. This is how ANSI escape sequences used to work back in the BBS days.

    But you could achieve what you want by doing:

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

    Here's a simple little function that does what you asked.

    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
    
    0 讨论(0)
  • 2020-11-28 08:05

    Find advanced function Write-HostColored below, which allows embedding coloring instructions in a string, both for the foreground and the background color:

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

    The above yields:

    In addition to accepting a default foreground and background color with -ForegroundColor and -BackgroundColor, 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 implicitly up to the end of the string, is written in that color.


    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 }
        }
    }
    
    0 讨论(0)
  • 2020-11-28 08:05

    So here's something I came up with. Hope it helps someone out.

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

    Can be used thus;

    $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
    

    Or whatever other combination you choose.

    0 讨论(0)
提交回复
热议问题