我想用一个语句输出许多不同的前景色。
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
这个输出是洋红色的,但我希望红色这个词的颜色是红色,而通过一个命令我想要蓝色代表蓝色。我怎样才能做到这一点?
编辑(2018年5月7日):我已将Write-Color更新为0.5并将其作为模块发布。此外,代码现已发布在github上。
0.5的变化:
变化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"
它实际上带来了对Josh脚本的额外检查和功能。
我试图在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给了我这个奇妙的功能!!
如果你在我的情况下,我已经从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色支持。
这是一种简单的方法
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;
}
您可以滚动自己的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
这个函数提供不同的语法糖:
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
这是一个小函数我写的输出彩色文本(它实际上更小,但我重写它更容易理解):
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
您可以将它放在$profile
文件中,以便在简单的PowerShell提示符中使用它,或者只是将其添加到某些脚本中。
这也有效......
Write-Host "Don't forget to " -ForegroundColor Yellow -NoNewline; Write-Host "CALL YOUR MOM " -ForegroundColor Red -NoNewline; Write-Host "every day!" -ForegroundColor Yellow
我在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没有连接或组合文本,它只是没有将光标移动到下一行。
在下面找到高级函数Write-HostColored
,它允许在字符串中嵌入着色指令,包括前景色和背景色:
Write-HostColored "I'm #green#green#, I'm #red#red#, and I'm #blue:white#blue on white#."
以上产量:
除了使用-ForegroundColor
和-BackgroundColor
接受默认前景色和背景色之外,您还可以使用以下语法在要写入的字符串中嵌入一个或多个颜色规范:
#<fgcolor>[:<bgcolor>]#<text>#
<fgcolor>
和<bgcolor>
必须是有效的[ConsoleColor]
值,例如green
或white
(情况无关紧要)。跟随颜色规范直到下一个#
,或隐含地直到字符串末尾的所有内容都以该颜色书写。
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 }
}
}
此代码具有不同数量的参数: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
列表用法(仅2个backGroundColor和4个foreGroundColor):
Write-Color (@(100..115) | %{" -> $_ : ".PadRight(30) + "`n"}) -ForeGroundColor cyan, yellow, magenta, red -BackGroundColor gray, black
标准写主机
Write-Host (@(100..115) | %{" -> $_ : ".PadRight(30) + "`n"}) -BackgroundColor gray
稍微修改一下......我拿了版本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 " "