1. Overview

In Linux terminals, the code to format text may differ. On the one hand, we can use the SGR (Select Graphic Rendition) parameters of ANSI escape codes, a standard cross-language way of encoding color and format data. Otherwise, the tput command may have the same effects, but its use is limited.

In this tutorial, we’ll focus on ANSI codes to format text in the GNOME Terminal, Konsole, and XFCE4 Terminal. Our examples will work equally on such terminals unless otherwise stated.

2. ANSI Codes Cross-Language Compatibility

We can send ANSI escape sequences to the Linux terminal.

They start with a CSI (Control Sequence Introducer) — the ASCII ESC (#27) character followed by an open square bracket [. Then, there is a code or a series of codes separated by a semicolon. Finally, the letter m indicates that the whole sequence is an SGR to set the graphic attributes.

The CSI can be \e[, \033[, \x1B[, or \u001B[. These are just alternative representations of the same thing, and the one we use depends on the programming language we’re using. More specifically, \e, \033, and others are different ways of indicating the ESC character.

Each code has two forms:

  • a number, such as 1
  • a pair of numbers separated by a colon, such as 4:3

For example, the following SGR sets the bold (code 1), italic (code 3), and underlined (code 4) styles:

\e[1;3;4m

Usually, an SGR like [0m or [m follows the formatted text to reset the styles. So, the following string is “Hello Baeldung” in bold, italic, and underlined:

\e[1;3;4mHello Baeldung\e[0m

Let’s try it with Bash:

EscapeSequenceExample-BashThen, let’s see Python3, replacing the non-supported CSI \e[ with \033[:

Escape Sequence Example Python3Likewise, Perl gives the same result:

EscapeSequenceExample-PerlIt’s the same for compiled programs like C:

#include <stdio.h>
int main()
{
    printf("\e[1;3;4mHello Baeldung\e[0m");
    printf("\n"); // adds a new line
    return 0;
}

Let’s save it as test.c, compile it, and run it:

EscapeSequenceExample-CJava has similar options. Regarding the CSI, both \e[ and \033[ are generally well supported, except for the Python3 version we tested. \x1B[ is also widely used. In other cases, such as Java, the CSI is \u001B[.

In the upcoming examples, we’ll focus only on Bash.

3. Font Style

This section is a cheat sheet for the most common cases of text styling.

Each style has an SGR that sets and resets it. It’s kind of like the opening and closing HTML tags. In contrast, \e[m and \e[0m reset all styles.

3.1. Code Snippet With the Most Common SGR

To keep the code as readable and reusable as possible, we placed each SGR in a Bash variable:

reset="\e[m"                # ANSI CODE 0   → resets all styles, it's the same of \e[0m

bold="\e[1m"                # ANSI CODE 1   → increases intensity, with a slight color change
rbold="\e[22m"              # ANSI CODE 22  → resets bold or dim (they are mutually exclusive styles)

dim="\e[2m"                 # ANSI CODE 2   → decreases intensity, with a slight color change
rdim="\e[22m"               # ANSI CODE 22  → resets bold or dim (they are mutually exclusive styles)

italic="\e[3m"              # ANSI CODE 3   → italic
ritalic="\e[23m"             # ANSI CODE 23  → resets italic

underline="\e[4m"           # ANSI CODE 4   → underline
runderline="\e[24m"         # ANSI CODE 24  → resets underline or doubleunderline (they are mutually exclusive styles)

doubleunderline="\e[21m"    # ANSI CODE 21  → double underline (not supported by Konsole)
rdoubleunderline="\e[24m"   # ANSI CODE 24  → resets underline or doubleunderline (they are mutually exclusive styles)

curlyunderline="\e[4:3m"    # ANSI CODE 4:3 → curly underline (not supported by Konsole)
rcurlyunderline="\e[4:0m"   # ANSI CODE 4:0 → resets curly underline

blink="\e[5m"               # ANSI CODE 5   → blink
rblink="\e[25m"             # ANSI CODE 25  → resets blink

reverse="\e[7m"             # ANSI CODE 7   → swaps text and background colors
rreverse="\e[27m"           # ANSI CODE 27  → resets reverse

hidden="\e[8m"              # ANSI CODE 8   → characters not displayed, helpful for passwords
rhidden="\e[28m"            # ANSI CODE 28  → resets hidden

strikethrough="\e[9m"       # ANSI CODE 9   → characters crossed by a central line
rstrikethrough="\e[29m"     # ANSI CODE 29  → resets strikethrough

overline="\e[53m"           # ANSI CODE 53 → overline
roverline="\e[55m"          # ANSI CODE 55 → resets overline

In fact, we can copy this code snippet in any Bash script. The next step is to try all these styles in a Linux terminal.

3.2. Examples of All Styles

Let’s test all the SGRs in a script, after inserting the previous code snippet in place of [SGR declarations]:

#!/usr/bin/env bash

[SGR declarations]

echo -e "\
${bold}Bold Example Text${rbold} \n\n\
${dim}Dim Example Text${rdim} \n\n\
${italic}Italic Example Text${ritalic} \n\n\
${underline}Underline Example Text${runderline} \n\n\
${doubleunderline}Double Underline Example Text${rdoubleunderline} \n\n\
${curlyunderline}Curly Underline Example Text${rcurlyunderline} \n\n\
${blink}Blink Example Text${rblink} \n\n\
${reverse}Reverse Example Text${rreverse} \n\n\
${hidden}Hidden Example Text${rhidden} <-- (Hidden text)\n\n\
${strikethrough}Strikethrough Example Text${rstrikethrough} \n\n\
${overline}Overline Example Text${roverline} \n\n\
Combining styles example:\n\
${bold}Hello Baeldung & ${italic}Hello ${curlyunderline}Linux${rcurlyunderline}${ritalic}${rbold}"

Let’s look at the result in GNOME Terminal:

GNOME Terminal Text Formatting ExampleThe last example shows how easy it is to combine our Bash variables. These all work in GNOME Terminal 3.44.0 and XFCE4 Terminal 0.8.10. In contrast, Konsole 21.12.3 doesn’t yet support double-underline or curly underline.

4. Colors

ASCII codes can indicate text and background colors based on a 16- or 256-color palette. However, we don’t really need to use this historical remnant, as the truecolor standard supports any RGB color.

All we need are the following SGRs, where instead of R, G, and B, we use a number from 0 to 255:

\e[38;2;R;G;Bm     #Select RGB foreground color
\e[48;2;R;G;Bm     #Select RGB background color

We can consult an RGB color table if we’re not familiar with RGB. Let’s test the colors yellow and black:

yellowText="\e[38;2;255;255;0m"
yellowBg="\e[48;2;255;255;0m"
blackText="\e[38;2;0;0;0m"
blackBg="\e[48;2;0;0;0m"
reset="\e[m"

echo -e "${yellowText}${blackBg}Yellow text${reset} - ${blackText}${yellowBg}Yellow background${reset}"

The result is as expected:

GNOME Terminal colorsRGB support is consistent between GNOME Terminal, Konsole, and XFCE4-Terminal.

5. Conclusion

In this article, we looked at text formatting and coloring in some popular Linux terminals.

In general, however, we should never assume that users’ terminals will support the ANSI codes we need. If we’re targeting a broad audience, extensive testing is always wise.

Comments are closed on this article!