Bat (batch) Sprache Wörter einzelnen färben?

2 Antworten

Vom Fragesteller als hilfreich ausgezeichnet

Zusätzlich zu den von Erzesel bereits genannten Methoden würde ich dir noch eine Methode empfehlen, die ich dafür fast ausschließlich angewandt hab.

Sie basiert auf dem Zusatzprogramm BatBox.exe, welches aber nicht heruntergeladen oder mitgeliefert werden muss, sondern einfach von der Batch erzeugt werden kann. (siehe :createBatBox unten)

Um Text anzuzeigen gibt es bei BatBox drei nützliche Befehle:

  1. batbox /g x y | x und y sind die Koordinaten, die angeben wo im Fenster der Text ausgegeben wird
  2. batbox /c 0xbf | legt die Farbe des Textes fest; b=Hintergrund, f=Vordergrund; die Farbcodes kannst du dir mit color/? anzeigen lassen.
  3. batbox /d "string" | gibt einen string aus

Hier mal ein Beispiel:

@echo off & color f0 & title ColorTest

::::::::::::::: check if batbox already exists :::::::::::::::
if not exist "%WINDIR%\system32\batbox.exe" call :createBatBox


::::::::::::::: the beginning of your program ::::::::::::::::

batbox /g 1 1 /c 0xec /d "MENU"
batbox /g 1 3 /c 0xf1 /d "option1"
batbox /g 1 4 /c 0xf1 /d "option2"
batbox /g 1 5 /c 0xf1 /d "option3"

::::::::::::::: the end of your program ::::::::::::::::::::::

exit

:createBatBox
if exist batbox.exe goto step2
 echo generiere batbox.exe ...
 for %%b in (
 4D5343460000000073030000000000002C000000000000000301010001000000
 00000000470000000100010000060000000000000000FE4259B5200062617462
 6F782E657865003FD9412724030006434BB5545F485361143F5737F0CF726B3A
 102ABB528B1EC24813421026D3529AB59C184460D7ED6EF7CE79EFB8F74A562F
 0B1D543EF5143DC60483C27AF0C14248B18710A4979ECA40426A0329A1B21ECA
 AF73EE9D4E21B287FAB6DF77CFF99DF37DDFEF3B3B779D1752C001800D5CC018
 808F1C1C3ED879A41015FB9F56C064E942ED141758A8ED96649D4F6A6A4C1306
 F8B0A028AAC1F789BC36A8F0B2C2B79E0DF1036A44ACDB557670638F601B4080
 E3A0C3FBFDDC06B7044EAE9CE34EA2283041C3B505A48E9E450079B99B69C05B
 FC4B1457BC75DD6666DECD8F981BE02EF71797FDC7A32E9A100C7C1EB1E505D9
 2CDD5BC7252AC57F1E92ABCA0771EB21D968029C98E76125D25F9967D1ED838C
 8372D6F24E093AD9175832FFADCAD43C7F8C459F9442D39D1E8C3947C6913F15
 7BB79A7BCD18CBA6D10BB24687B9E33226E4E6904E5DE37A9DE90A3C9C7926F1
 98F48C73E401F2CC731FBD66BAB2335D6E8689B0336A13E6798C76B601772CB6
 F7E2565EEAD64C1589A931C93092B34B2ECE4E1C6BB466EBE82C1DDD4E8A3ED3
 5ED25137B163B861AE9ED8B7D452F182D42F945F4D111213920E14F28B908D57
 B3C61233710903560539A9DA3CD0E257901F6EA600D664019744879B295EE44C
 3F43EF9BFD303A3FD172A61FE13CDABC17FD9BEBB39F5CD7DFD3BDEEF155565D
 6E63B4D8CC0E9EEF910E15745C5D47755EAB32AB245726A20A890C55275B4616
 952417A44035BA71FC8498670A970F3F77CCCD7E2862E3F524D44EBFBB6D741F
 3D46F7A4DF3847E885988B835574AF0EDE4893F9056F1874970F26101F111711
 B6DD3EA8411C472C20A611FD31211C8D0CA89737DAEC4665A1E532F8CA8DA13F
 ED2E7013682FBA7FDFA29DA11E7F57775D6B2000A7DBBACEB4051AEA4D077EE0
 02076E54833881E846488864FEB09DE2D8AAA2113222ED82124988E48744C3AF
 2ABA9A103BF17F6A3BD32D0E192D86A1C97D8386B82DE21FD474550BAABA6CC8
 AA42ABBA4421920F7628C941A385F213A298DCB6AE55D69309E18A79D40C6A9A
 47BC422C2356106B799D7F8AE16D345931A264F5C644232C9916990382AC085A
 4C475F1C920D93EFEF932C4B3734434D00FC02                          
 ) Do >>t.dat (Echo.For b=1 To len^("%%b"^) Step 2
 ECHO WScript.StdOut.Write Chr^(Clng^("&H"^&Mid^("%%b",b,2^)^)^) : Next)
 Cscript /b /e:vbs t.dat>batbox.ex_
 Del /f /q /a t.dat >nul 2>&1
 Expand -r batbox.ex_ >nul 2>&1
 Del /f /q /a batbox.ex_ >nul 2>&1
:step2
 echo verschiebe batbox nach system32 ...
 move "batbox.exe" "%WINDIR%\system32\"
 cls
exit /b

~Tim

Normalerweise ist Batch nicht dazu gedacht wie ein bunter Pfau aufzutreten.
Batch ist ein Werkzeug . Bei einem Schraubenzieher ist es doch auch irrelevant welche Farbe der Griff hat...

...und weil das so ist, gibt es auch keine wirklich vernünftige Methode einzelne Textstücke einzufärben.

Die universellste Methode wäre es ein Consolprogramm zu schreiben/ oder irgendwo runterzuladen , welches Bunte Schrift in die Console schreibt...
Dazu am Ende...

Wirklich Effizient ist keine der anschließend vorgestellten Methoden.

Die Findstr Methode:

@echo off
rem erzeuge ein BackSpace
for /F "delims=;" %%a in ('"prompt $H; & for %%. in (nix) do call "') do (set "BS=%%a")

rem call :xColor VordergrundHindergrund "text zu schreiben" [Zahl der Zeilenvorschübe]
rem Einschränkung: Sonderzeichen / \ : * ? " < > |  sind nicht zulässig oder es geht nur  mit weiterer Zauberei  
call :xColor fc "Du bist ein Held" 
call :xColor ce " der Arbeit $$$" 1
call :xColor 0C "Nach 4 Leerzeilen..." 5
call :xColor 5f "...geht  " 0
call :xColor 9b " es " & call :xColor 20 "weiter" 11

pause 
exit /b

:xColor
  rem parameters %1= colorcode  %2="text   "  [%3=Anzahl der Zeilenvorschübe]
  rem ohne parameter 3 schreibt der nächste Befehl in der gleichen Zeile  weiter
pushd %cd%
cd /d %temp%  
<nul set /p=%BS%>"%~2"
findstr /v /a:%1 /R "$" "%~2" nul 2>nul
del "%~2" > nul 2>&1
rem erzeuge Zeilenvorschübe
if not .%3==. (for /l %%n in (1,1,%3) do echo.)
popd
exit /b

Funktionsweise:
Findstr gibt mit parameter /a color im Resultat einen farbig hervorgehobenen Dateinamen: consolfarbig gefundene Zeichenkette aus.
...also schreiben wir ein Backspace in eine Datei deren Name unseren Text enthält.
Findstr zeigt den farbigen Dateinamen und Backspace löscht den Doppelpunkt.

Nachteile:

  • viele temporäre Datenträgerzugriffe
  • kann keine Sonderzeichen / \ : * ? " < > | ausgeben, diese sind in Dateinamen nicht erlaubt.

Die Powershell Methode:

@echo off 
rem erzeuge ein BackSpace
for /F "delims=;" %%a in ('"prompt $H; & for %%. in (nix) do call "') do (set "BS=%%a")

call :_color  15 12 "mein Text"
call :_color 9 14 "mein Text2" -nonewline
call :_color 0 11 " %bs%\- /3"
call :hex_color 2f "blub"
pause
exit /b

:hex_color
  rem parameters: %1= Zweistelliger Colorcode wie  bei Color   %2= "text"  [%3=-nonewline] ...unterdrückt  Zeilenvorschub
set "x=%1"
set /a "x1=0x%x:~0,1%"
set /a "x2=0x%x:~1,1%"
powershell -Command write-host '%2' %3 -foregroundcolor %x1% -backgroundcolor %x2%
exit /b
:_color
powershell -Command write-host '%3' %4 -foregroundcolor %1 -backgroundcolor %2
exit /b

Funktionsweise:

Ruft ein Inline-Powershellscript auf und benutzt das Cmtlet Writehost zum schreiben des Textes.

Nachteile:

  • Der wohl entscheidendste Nachteil ist die lange Ladezeit von Powershell und damit eine sehr langsame Ausgabe

Es wäre dann durchaus nützlich allen zusammenhängenden Text in einen einzelnen Powershell start zu verlegen und die Ausgabe Komplet in PS zu schreiben:

powershell -Command "&{write-host 'erster  text !' -nonewline -foregroundcolor 14 -backgroundcolor 1;write-host 'HuHuuuuh' -foregroundcolor 12 -backgroundcolor 15;write-host 'ist  da wer ?...'  -foregroundcolor 4 -backgroundcolor 0}"
pause
exit /b

externes Programm:

Wenn man eine Batch weitergeben will ist es wohl die dümmste Idee ein Programm zu verwenden, welches nicht zum System gehört.

Entweder Du lieferst es mit. (ich wäre skeptisch wenn mir jemand eine unbekannte .exe ins System schleust).
...oder du gibst an wo er dieses Drittanbieter Programm downloaden kann (das ist fast noch schlimmer).

Du kannst natürlich auch den Quelltext für ein Programm mitgeben und es auf dem Zielcomputer compileren lassen.

Das setzt natürlich Voraus, das der Kumpel einen passenden Installiert hat.

Inzwischen ist die DotNet Runtime auf fast jedem Windowscomputer installiert.

Ich hoffe Du hast die .Net Runtime installiert:

compile_xcolor.bat:

@if (@X)==(@Y) @end /* JScript comment
@echo off
setlocal
for /f "tokens=* delims=" %%v in ('dir /b /s /a:-d  /o:-n "%SystemRoot%\Microsoft.NET\Framework\*jsc.exe"') do (set "jsc=%%v")
if not exist "xcolor.exe" ("%jsc%" /nologo /out:"xcolor.exe" "%~0")

  rem Demonstration:
xcolor
echo:
xcolor -f 12 -b 1 -s "Hallo Welt" 
xcolor -f 15 -b 12 -s "Hallo Welt" -n
xcolor -f 4 -b 14 -s "Hallo Welt" -n
endlocal
pause
exit /b 
*/

import System;
var arguments:String[] = Environment.GetCommandLineArgs();
var newLine = false;
var output = "";
var foregroundColor = Console.ForegroundColor;
var backgroundColor = Console.BackgroundColor;
var evaluate = false;
var currentBackground=Console.BackgroundColor;
var currentForeground=Console.ForegroundColor;

var jsEscapes = {
  'n': '\n',
  'r': '\r',
  't': '\t',
  'f': '\f',
  'v': '\v',
  'b': '\b'
};

function decodeJsEscape(_, hex0, hex1, octal, other) {
  var hex = hex0 || hex1;
  if (hex) { return String.fromCharCode(parseInt(hex, 16)); }
  if (octal) { return String.fromCharCode(parseInt(octal, 8)); }
  return jsEscapes[other] || other;
}

function decodeJsString(s) {
  return s.replace(
      // Matches an escape sequence with UTF-16 in group 1, single byte hex in group 2,
      // octal in group 3, and arbitrary other single-character escapes in group 4.
      /\\(?:u([0-9A-Fa-f]{4})|x([0-9A-Fa-f]{2})|([0-3][0-7]{0,2}|[4-7][0-7]?)|(.))/g,
      decodeJsEscape);
}

function printHelp( ) {
   print( arguments[0] + "  -s string [-f foreground] [-b background] [-n] [-e]" );
   print( " " );
   print( "   string          String to be printed" );
   print( "   foreground       Foreground color - a " );
   print( "               number between 0 and 15." );
   print( "   background       Background color - a " );
   print( "               number between 0 and 15." );
   print( "   -n               Indicates if a new line should" );
   print( "               be written at the end of the ");
   print( "               string(by default - no)." );
   print( "   -e               Evaluates special character " );
   print( "               sequences like \\n\\b\\r and etc ");
   print( "" );
   print( "Colors :" );
   for ( var c = 0 ; c < 16 ; c++ ) {
      Console.BackgroundColor = c;
      Console.Write( " " );
      Console.BackgroundColor=currentBackground;
      Console.Write( "-"+c );
      Console.WriteLine( "" );
   }
   Console.BackgroundColor=currentBackground;
}

function errorChecker( e:Error ) {
      if ( e.message == "Input string was not in a correct format." ) {
         print( "the color parameters should be numbers between 0 and 15" );
         Environment.Exit( 1 );
      } else if (e.message == "Index was outside the bounds of the array.") {
         print( "invalid arguments" );
         Environment.Exit( 2 );
      } else {
         print ( "Error Message: " + e.message );
         print ( "Error Code: " + ( e.number & 0xFFFF ) );
         print ( "Error Name: " + e.name );
         Environment.Exit( 666 );
      }
}

function numberChecker( i:Int32 ){
   if( i > 15 || i < 0 ) {
      print("the color parameters should be numbers between 0 and 15");
      Environment.Exit(1);
   }
}

if ( arguments.length == 1 || arguments[1].toLowerCase() == "-help" || arguments[1].toLowerCase() == "-help"   ) {
   printHelp();
   Environment.Exit(0);
}

for (var arg = 1; arg <= arguments.length-1; arg++ ) {
   if ( arguments[arg].toLowerCase() == "-n" ) {
      newLine=true;
   }
   if ( arguments[arg].toLowerCase() == "-e" ) {
      evaluate=true;
   }
   if ( arguments[arg].toLowerCase() == "-s" ) {
      output=arguments[arg+1];
   }
   if ( arguments[arg].toLowerCase() == "-b" ) {
      try {
         backgroundColor=Int32.Parse( arguments[arg+1] );
      } catch(e) {
         errorChecker(e);
      }
   }

   if ( arguments[arg].toLowerCase() == "-f" ) {
      try {
         foregroundColor=Int32.Parse(arguments[arg+1]);
      } catch(e) {
         errorChecker(e);
      }
   }
}

Console.BackgroundColor = backgroundColor ;
Console.ForegroundColor = foregroundColor ;

if ( evaluate ) {
   output=decodeJsString(output);
}

if ( newLine ) {
   Console.WriteLine(output);   
} else {
   Console.Write(output);

}

Console.BackgroundColor = currentBackground;
Console.ForegroundColor = currentForeground;

Den Javascript-Code habe ich nicht geschrieben (warum sollte ich das Rad ein Zweites mal erfinden) , ich weis aber auch nicht mehr wo ich den Aufgefischt habe der lungert schon eine halbe Ewigkeit auf in meiner Programm code Bibliothek herum...
Wenn Du einmal die xcolor.exe hast kannst Du sie verwenden ohne sie jedesmal neu zu compilieren.

Nachteil:
.Net muss auch zum Ausführen installiert sein . (JScript.Net ist nicht C oder C++)

Mehr fällt mir im Moment nicht ein. ...aber ich Denke das gibt Dir genug Stoff zum Experimentieren...

Woher ich das weiß:eigene Erfahrung – Ich mach das seit 30 Jahren
Erzesel  22.04.2018, 12:58
@Kieselsaeure

Das ist Ja die Problematik , auch um ein C++ Programm zu compilieren benötigt man die Installation eines entsprechenden Compilers.
Da ist die Chance das .Net installiert wesentlich größer.

Wie bereits gesagt der Aufwand ist einfach zu groß, nur um ein Paar Zeilen in einer Batch Bunt zu machen. Dafür reicht dann im Prinzip Findstr oder PS.

Findstr gibt' seit DOS
...und PS ist ab Windows 7 Standard.

0
LordFuFu 
Fragesteller
 22.04.2018, 15:34

okey danke für die lange aber komplizierte antwort ich schau Mal ob ich was damit anfangen kann :)

0
Erzesel  22.04.2018, 17:03

Ist doch nix kompliziertes dran. Für Batchkünstler ist das trivial... noch einfacher läßt es sich kaum erklären. ...Dabei habe ich mir bereits Mühe gegeben das Ganze in möglichst einfache Worte zu fassen... Da scheinen sich schon Welten im allgemeinen Sprachgebrauch aufzutun... o.O Der Code selbst lässt sich ohnehin nicht weiter vereinfachen Batch oder Multisprach-Chimera (Mix aus verschiedenen Programmiersprachen) ist immer Komplex, wenn es Darum geht eine Unmöglichkeit aufzulösen. und bunter Text ist in Batch eigentlich nicht Vorgesehen.

1