Sie können dies tun, indem Sie durch einen Filter leiten. Es ist lediglich eine Frage des Hinzufügens geeigneter ANSI-Codes vor und nach jeder Zeile:
http://en.wikipedia.org/wiki/ANSI_escape_sequences#Colors
Ich konnte kein Tool finden, das dies tatsächlich nach ein paar Minuten googelt, was etwas seltsam ist, wenn man bedenkt, wie einfach es wäre, eines zu schreiben.
Hier ist eine Idee mit C:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
/* std=gnu99 required */
// ANSI reset sequence
#define RESET "\033[0m\n"
// length of RESET
#define RLEN 5
// size for read buffer
#define BUFSZ 16384
// max length of start sequence
#define START_MAX 12
void usage (const char *name) {
printf("Usage: %s [-1 N -2 N -b -e | -h]\n", name);
puts("-1 is the foreground color, -2 is the background.\n"
"'N' is one of the numbers below, corresponding to a color\n"
"(if your terminal is not using the standard palette, these may be different):\n"
"\t0 black\n"
"\t1 red\n"
"\t2 green\n"
"\t3 yellow\n"
"\t4 blue\n"
"\t5 magenta\n"
"\t6 cyan\n"
"\t7 white\n"
"-b sets the foreground to be brighter/bolder.\n"
"-e will print to standard error instead of standard out.\n"
"-h will print this message.\n"
);
exit (1);
}
// adds character in place and increments pointer
void appendChar (char **end, char c) {
*(*end) = c;
(*end)++;
}
int main (int argc, char *const argv[]) {
// no point in no arguments...
if (argc < 2) usage(argv[0]);
// process options
const char options[]="1:2:beh";
int opt,
set = 0,
output = STDOUT_FILENO;
char line[BUFSZ] = "\033[", // ANSI escape
*p = &line[2];
// loop thru options
while ((opt = getopt(argc, argv, options)) > 0) {
if (p - line > START_MAX) usage(argv[0]);
switch (opt) {
case '?': usage(argv[0]);
case '1': // foreground color
if (
optarg[1] != '\0'
|| optarg[0] < '0'
|| optarg[0] > '7'
) usage(argv[0]);
if (set) appendChar(&p, ';');
appendChar(&p, '3');
appendChar(&p, optarg[0]);
set = 1;
break;
case '2': // background color
if (
optarg[1] != '\0'
|| optarg[0] < '0'
|| optarg[0] > '7'
) usage(argv[0]);
if (set) appendChar(&p, ';');
appendChar(&p, '4');
appendChar(&p, optarg[0]);
set = 1;
break;
case 'b': // set bright/bold
if (set) appendChar(&p, ';');
appendChar(&p, '1');
set = 1;
break;
case 'e': // use stderr
output = STDERR_FILENO;
break;
case 'h': usage(argv[0]);
default: usage(argv[0]);
}
}
// finish 'start' sequence
appendChar(&p, 'm');
// main loop
// set non-block on input descriptor
int flags = fcntl(STDIN_FILENO, F_GETFL, 0);
fcntl(STDIN_FILENO, F_SETFL, flags | O_NONBLOCK);
// len of start sequence
const size_t slen = p - line,
// max length of data to read
rmax = BUFSZ - (slen + RLEN);
// actual amount of data read
ssize_t r;
// index of current position in output line
size_t cur = slen;
// read buffer
char buffer[rmax];
while ((r = read(STDIN_FILENO, buffer, rmax))) {
if (!r) break; // EOF
if (r < 1) {
if (errno == EAGAIN) continue;
break; // done, error
}
// loop thru input chunk byte by byte
// this is all fine for utf-8
for (int i = 0; i < r; i++) {
if (buffer[i] == '\n' || cur == rmax) {
// append reset sequence
for (int j = 0; j < RLEN; j++) line[j+cur] = RESET[j];
// write out start sequence + buffer + reset
write(output, line, cur+RLEN);
cur = slen;
} else line[cur++] = buffer[i];
}
}
// write out any buffered data
if (cur > slen) {
for (int j = 0; j < RLEN; j++) line[j+cur] = RESET[j];
write(output, line, cur+RLEN);
}
// flush
fsync(output);
// the end
return r;
}
Ich denke, das ist ungefähr so effizient, wie Sie es sich vorstellen können. Die write()
Notwendigkeit, eine ganze Zeile mit den ANSI-Sequenzen auf einmal zu erstellen - das Testen mit parallelen Gabeln führte zu einer Verschachtelung, wenn die ANSI-Sequenzen und der Pufferinhalt getrennt durchgeführt wurden.
Das muss kompiliert werden, -std=gnu99
da getopt
es nicht Teil des C99-Standards ist, sondern Teil von GNU. Ich habe dies etwas mit parallelen Gabeln getestet; Diese Quelle, ein Makefile und die Tests befinden sich hier in einem Tarball:
http://cognitivedissonance.ca/cogware/utf8_colorize/utf8_colorize.tar.bz2
Wenn die Anwendung, die Sie mit Protokollen verwenden, einen Standardfehler aufweist, denken Sie daran, dies ebenfalls umzuleiten:
application 2>&1 | utf8-colorize -1 2 &
Die .sh-Dateien im Testverzeichnis enthalten einige Verwendungsbeispiele.