23

Is it possible to change the font attributes of the output of echo in either zsh or bash?

What I would like is something akin to:

echo -n "This is the font: normal "
echo -n $font=italic "italic,"
echo -n $font=bold "bold,"
echo -n "and"
echo -n $font=small "small".

so that it print: "This is the font: normal, italic, bold, small" within a line of text.

5 Answers5

24

On most if not all terminal emulators, you can't set different font sizes or different fonts, only colors and a few attributes (bold, underlined, standout).

In bash (or in zsh or any other shell), you can use the terminal escape sequences directly (apart from a few exotic ones, all terminals follow xterm's lead these days). CSI is ESC [, written $'\e[' in bash. The escape sequence to change attributes is CSI Ps m.

echo $'\e[32;1mbold red\e[0mplain\e[4munderlined'

Zsh has a convenient function for that.

autoload -U colors
colors
echo $bold_color$fg[red]bold red${reset_color}plain$'\e['$color[underline]munderlined

Or can do it as part of prompt expansion, also done with print -P, or the % parameter expansion flag:

print -P '%F{red}%Bbold%b red%f %Uunderline%u'
20

You could include these color definitions in a script or source file. Could look something like this.

#!/bin/bash
PATH=/bin:/usr/bin:

NONE='\033[00m'
RED='\033[01;31m'
GREEN='\033[01;32m'
YELLOW='\033[01;33m'
PURPLE='\033[01;35m'
CYAN='\033[01;36m'
WHITE='\033[01;37m'
BOLD='\033[1m'
UNDERLINE='\033[4m'

echo -e "This text is ${RED}red${NONE} and ${GREEN}green${NONE} and ${BOLD}bold${NONE} and ${UNDERLINE}underlined${NONE}."

tput sgr0

Notice that you should reset the ANSI color codes after each instance you invoke a change. The tput sgr0 resets all changes you have made in the terminal.

I believe changing the font size or italics would be specific to the terminal you are using.

While this guide is specific to customizing your bash prompt, it is a good reference for color codes and generates some ideas of what you can do.

George M
  • 13,959
8

Seems as if the layout can't handle the [0x1b]-character in front of the [.

The first line makes bold:

 echo -e "\x1b[1m bold"
     echo -e "\x1b[30m black"
     echo -e "\x1b[31m red"
     echo -e "\x1b[32m green"
     echo -e "\x1b[33m yellow"
     echo -e "\x1b[34m blue"
     echo -e "\x1b[35m mag"
     echo -e "\x1b[36m cyan"
     echo -e "\x1b[37m white"   

For the general type, I only know

echo -e "\x1b[0m io-std"
echo -e "\x1b[1m bold"
echo -e "\x1b[2m normal"

and from the comments, thanks manatwork and GypsyCosmonaut:

echo -e "\x1b[3m italic"
echo -e "\x1b[4m underlined"
echo -e "\x1b[5m blinking"
echo -e "\x1b[7m inverted"

and don't know the difference between io-std and normal.

I haven't seen italic or small in the shell.

You can enter them (thanks to manatwork too) by Ctrl + v ESC in the Bash, where it will be displayed as ^[. This mean the whole ANSI sequence will look like ^[[1m bold or ^[[1mbold (to avoid the blank before 'bold').

Many editors have problems with (char)0x1b. Alternatives: copy/paste it from somewhere, or use

echo -e "\x1b[1m bold"

in bash, or a hex editor.

Or, even simpler:

echo -e "\e[1m bold"

The \e is an escape sequence for the ascii code 27, for the bash internal command echo as well as for the external program GNU-echo.

user unknown
  • 10,482
2

Note that for letters in the latin script specifically (there are also options for letters in other scripts, but more limited), Unicode has mathematical characters with various rendering attributes. For instance, for a/A, there's:

U+1D400 MATHEMATICAL BOLD CAPITAL A
U+1D41A MATHEMATICAL BOLD SMALL A
U+1D434 MATHEMATICAL ITALIC CAPITAL A
U+1D44E MATHEMATICAL ITALIC SMALL A
U+1D468 MATHEMATICAL BOLD ITALIC CAPITAL A
U+1D482 MATHEMATICAL BOLD ITALIC SMALL A
U+1D49C MATHEMATICAL SCRIPT CAPITAL A
U+1D4B6 MATHEMATICAL SCRIPT SMALL A
U+1D4D0 MATHEMATICAL BOLD SCRIPT CAPITAL A
U+1D4EA MATHEMATICAL BOLD SCRIPT SMALL A
U+1D504 MATHEMATICAL FRAKTUR CAPITAL A
U+1D51E MATHEMATICAL FRAKTUR SMALL A
U+1D538 MATHEMATICAL DOUBLE-STRUCK CAPITAL A
U+1D552 MATHEMATICAL DOUBLE-STRUCK SMALL A
U+1D56C MATHEMATICAL BOLD FRAKTUR CAPITAL A
U+1D586 MATHEMATICAL BOLD FRAKTUR SMALL A
U+1D5A0 MATHEMATICAL SANS-SERIF CAPITAL A
U+1D5BA MATHEMATICAL SANS-SERIF SMALL A
U+1D5D4 MATHEMATICAL SANS-SERIF BOLD CAPITAL A
U+1D5EE MATHEMATICAL SANS-SERIF BOLD SMALL A
U+1D608 MATHEMATICAL SANS-SERIF ITALIC CAPITAL A
U+1D622 MATHEMATICAL SANS-SERIF ITALIC SMALL A
U+1D63C MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL A
U+1D656 MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL A
U+1D670 MATHEMATICAL MONOSPACE CAPITAL A
U+1D68A MATHEMATICAL MONOSPACE SMALL A

So, if you can't use graphic rendering escape sequences because for instance it's to be displayed on something other than a terminal, you could use those.

italic() {
  sed 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz//'
}
$ echo Hellow World | italic

0

Here:

http://en.wikipedia.org/wiki/ANSI_escape_code

(note: a lot of them usually don't work, but most of these are marked thus.)

I'm making a game in the terminal and have been relying heavily on the above link. It even tells you how to hide/unhide the cursor, make color (30's), "bold" (lighter), darker, underlined, italic, background color (40's instead of 30's), etc. You can also change the cursor's location (which is very helpful - for example, "\x1B[1A" moves the cursor up one line; "\x1B[0;0H" moves the cursor to row 0, col 0; "\x1B[2J" clears the screen; "\x1B[2K" clears the line.

For your purposes as people have said:

echo -e "\x1b[30;44m black with blue background \x1b[m"
echo -e "\x1b[31;42m red with green background \x1b[m"
echo -e "\x1b[32;40m green with black background \x1b[m"
echo -e "\x1b[8m Invisible; na na na na boo boo \x1b[m"

Note: You need the -e in:

echo -e "\x1b[35;1m Light purple \x1b[m"

or you need to use single quotes. Type man echo to see why (double quotes are usually a pain when printing; when I need stuff to not expand or I need ANSI escape sequences, I use single quotes because it is easy - even though I gotten used to it from doing it so many times - to forget the -e in which case you get "box with numbers and letters[35;1m").

Every time you see CSI replace it with "\x1b[" (or "\e[" or "\u1b["). "\x1b[" I think is more standard, but I don't really know what the difference is between them is.

AdminBee
  • 22,803
Dylan
  • 435
  • If you like cluttering your strings with extra characters, don't use \e :-) – clearlight Jan 15 '17 at 21:01
  • @clearlight I am not sure what you mean. I think you might have meant to say "use \e". However, \e is less supported than \x1b I have found. The optimal thing to do would be either esc=$'\e' or esc=$'\x1b' (this is in bash) and then use "${esc}[34;1m" (for, e.g., bright blue). I have a semi-complex example here (https://github.com/dylnmc/ps1porn/blob/master/powerline.sh) for a real bash prompt string ;) Please forgive the name of the repo -- you can thank people in freenode's channel #archlinux-offtopic for that. – Dylan Feb 03 '17 at 17:37
  • Reason for doing esc=$'\e' is that this allows bash to create the ansi-escape character on the spot, and you benefit from it in a couple of ways. Sometimes, in fact, (as is demonstrated in the github link), you have to use this method in order to get color to show up properly. For older versions of bash as well as the sh shell, you should (but don't need to) use this method to get color to show up ... granted that the terminal uses the escape sequences that most modern terminals do. – Dylan Feb 03 '17 at 18:05