Przekazanie polecenia przez filtr kolorów

13

Czy coś takiego istnieje w Uniksie?

$ echo "this should show in red" | red
$ echo "this should show in green" | green
$ echo "this should show in blue" | blue

Nie mam tu na myśli dosłownego tekstu kodu koloru (na przykład wklejenia do pliku). Chodzi mi o to, aby tekst rzeczywiście pojawił się w terminalu jako ten kolor. czy to możliwe?

Jerzy
źródło

Odpowiedzi:

14

Oto mały skrypt, który właśnie to robi. Zapisz to jak colorw katalogu w swoim $PATH(na przykład, ~/binjeśli jest w twoim $PATH):

#!/usr/bin/env perl

use strict;
use warnings;
use Term::ANSIColor; 

my $color=shift;
while (<>) {
    print color("$color").$_.color("reset");
} 

Następnie przeprowadź tekst przez skrypt, podając .jako wzór do dopasowania i określając kolor:

zrzut ekranu terminala uruchamiającego skrypt

Obsługiwane kolory zależą od możliwości twojego terminala. Aby uzyskać więcej informacji, zobacz dokumentację na Term::ANSIColoropakowaniu.

terdon
źródło
Czy istnieje lista kolorów, które można przekazać gdzieś?
George
@ George, który zależy od konfiguracji. Jeśli masz RGB obsługującej terminal można nawet użyć rzeczy podoba rgb001, rgb123itp See perldoc.perl.org/Term/ANSIColor.html#Supported-Colors więcej szczegółów.
terdon
23

Użyłbyś tputdo tego:

tput setaf 1
echo This is red
tput sgr0
echo This is back to normal

Można to wykorzystać do zbudowania potoku:

red() { tput setaf 1; cat; tput sgr0; }
echo This is red | red

Podstawowe kolory to odpowiednio czarny (0), czerwony (1), zielony, żółty, niebieski, magenta, cyjan i biały (7). Wszystkie szczegóły znajdziesz na stronie terminfo(5)podręcznika .

Stephen Kitt
źródło
6

Z zsh:

autoload colors; colors
for color (${(k)fg})
  eval "$color() {print -n \$fg[$color]; cat; print -n \$reset_color}"

I wtedy:

$ echo "while" | blue
while
Stéphane Chazelas
źródło
1

(jak omówiono w komentarzach, użyjtput zamiast tego, jeśli masz)

Za pomocą powłoki bourne i echo(wbudowanego) polecenia, które rozumie ucieczkę ANSI \ez -eopcją:

black()  { IFS= ; while read -r line; do echo -e '\e[30m'$line'\e[0m'; done; }
red()    { IFS= ; while read -r line; do echo -e '\e[31m'$line'\e[0m'; done; }
green()  { IFS= ; while read -r line; do echo -e '\e[32m'$line'\e[0m'; done; }
yellow() { IFS= ; while read -r line; do echo -e '\e[33m'$line'\e[0m'; done; }
blue()   { IFS= ; while read -r line; do echo -e '\e[34m'$line'\e[0m'; done; }
purple() { IFS= ; while read -r line; do echo -e '\e[35m'$line'\e[0m'; done; }
cyan()   { IFS= ; while read -r line; do echo -e '\e[36m'$line'\e[0m'; done; }
white()  { IFS= ; while read -r line; do echo -e '\e[37m'$line'\e[0m'; done; }

echo '    foo\n    bar' | red

lub bardziej ogólny skrypt powłoki (powiedzmy /usr/local/bin/colorize):

#!/bin/sh

usage() {
    echo 'usage:' >&2
    echo '  some-command | colorize {black, red, green, yellow, blue, purple, cyan, white}' >&2
    exit 1
}

[ -z "$1" ] && usage

case $1 in
    black)  color='\e[30m' ;;
    red)    color='\e[31m' ;;
    green)  color='\e[32m' ;;
    yellow) color='\e[33m' ;;
    blue)   color='\e[34m' ;;
    purple) color='\e[35m' ;;
    cyan)   color='\e[36m' ;;
    white)  color='\e[36m' ;;
    *) usage ;;
esac

IFS=
while read -r line; do
    echo -e $color$line'\e[0m'
done

IFS=jest potrzebny, aby zapobiec przycinaniu białych znaków (szczegóły w POSIX ).

jak działa IFS

wataash
źródło
Radzę preferować używanie tput.
LinuxSecurityFreak
Jest to całkowicie nieprzenośne rozwiązanie. Mam na myśli, że powinieneś stosować się do POSIX.
LinuxSecurityFreak
1
Jasne, gdybyśmy mogli. Jest przeznaczony do stosowania w systemach wbudowanych lub środowiskach ratowniczych, takich jak busybox. Postanowiłem napisać tę odpowiedź, ponieważ uważam, że te fragmenty kodu są przydatne w niektórych sytuacjach - przynajmniej dla użytkowników busyboksa i dla mnie, którzy musieli wyświetlać kolory tylko za pomocą wbudowanych poleceń powłoki w środowisku osadzonym.
wataash
zapomniałem powiedzieć, że zwykły busybox nie ma tput.
wataash