70

I have a command that produces output in color, and I would like to pipe it into a file with the color codes stripped out. Is there a command that works like cat except that it strips color codes? I plan to do something like this:

$ command-that-produces-colored-output | stripcolorcodes > outfile
Ryan C. Thompson
  • 5,398
  • 6
  • 29
  • 23
  • 4
    It might be a bug that a program produces colored output even then it's output is redirected to a file _and_ doesn't provide an option to switch it off. I'd expect any program that colors it's output to check `isatty(stdin)` before doing so. Mind to share what is that program? – alex Dec 04 '10 at 06:44
  • pass it through `cat` - quick test I ran `grep --color=auto myusername /etc/passwd` gives me my username in red with white text elsewhree. `grep --color=auto myusername /etc/passwd | cat` gives me plain white text – ivanivan Nov 15 '17 at 02:48
  • 3
    That's not a solution. It only works because `grep --color=auto` avoids producing colored output when standard output is not a terminal. I'm talking about a command that unconditionally outputs color codes. (As alex points out above, such behavior is arguably a bug, but sometimes we need to work with imperfect software that we can't easily fix ourselves, and that's what this question is about.) – Ryan C. Thompson Nov 15 '17 at 04:00
  • Possibly relevant https://unix.stackexchange.com/questions/14684/removing-control-chars-including-console-codes-colours-from-script-output – Chris Stryczynski Jun 10 '18 at 14:22
  • Reinforcing Ryan's post: `grep --colour=always myusername /etc/passwd | cat` keeps the username in red. –  Aug 25 '22 at 08:36
  • [ansi2txt](https://superuser.com/a/1513099/642842) – Shadi Jan 25 '23 at 21:30

7 Answers7

64

You'd think there'd be a utility for that, but I couldn't find it. However, this Perl one-liner should do the trick:

perl -pe 's/\e\[?.*?[\@-~]//g'

Example:

$ command-that-produces-colored-output | perl -pe 's/\e\[?.*?[\@-~]//g' > outfile

Or, if you want a script you can save as stripcolorcodes:

#! /usr/bin/perl

use strict;
use warnings;

while (<>) {
  s/\e\[?.*?[\@-~]//g; # Strip ANSI escape codes
  print;
}

If you want to strip only color codes, and leave any other ANSI codes (like cursor movement) alone, use

s/\e\[[\d;]*m//g;

instead of the substitution I used above (which removes all ANSI escape codes).

cjm
  • 26,740
  • 12
  • 88
  • 84
  • 11
    As mentioned in a comment to another answer (http://unix.stackexchange.com/questions/4527/program-that-passes-stdin-to-stdout-with-color-codes-stripped#4531), this regex was pulled from `Term::ANSIColor`. Acknowledge your sources, please! – forivall Nov 22 '13 at 00:13
  • 2
    acknowledge your sources! – Jürgen Paul May 21 '14 at 11:15
33

Remove color codes (special characters) with GNU sed

sed -r "s/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]//g"

Or

Strip ANSI escape sequences in Python

Install colorama python package (pip install colorama). Put into stripcolorcodes:

#!/usr/bin/env python
import colorama, fileinput, sys;
colorama.init(strip=True);

for line in fileinput.input():
    sys.stdout.write(line)

Run chmod +x stripcolorcodes.

Stéphane Chazelas
  • 522,931
  • 91
  • 1,010
  • 1,501
jfs
  • 894
  • 2
  • 12
  • 31
  • 2
    Didn't try python, but the sed version doesn't strip all colors. (I didn't test exhaustively, but it left some background colors intact, so I went with the faster perl option.) – rsaw Jan 17 '18 at 23:48
23

If you can install the Term::ANSIColor module, this perl script works:

#!/usr/bin/env perl
use Term::ANSIColor qw(colorstrip);
print colorstrip $_ while <>;
ephemient
  • 15,640
  • 5
  • 49
  • 39
Ryan C. Thompson
  • 5,398
  • 6
  • 29
  • 23
  • 8
    That's actually where I got that color-codes-only regex. But installing a whole module just for that one regex is a bit much. – cjm Dec 04 '10 at 02:00
  • 5
    Meh, if you set up cpanm correctly, it installs the module in about 5 seconds. – Ryan C. Thompson Dec 04 '10 at 09:30
  • 1
    There is no need to write the script to the file. Just pipe into: `perl -mTerm::ANSIColor=colorstrip -n -e 'print colorstrip $_'` – Jesse Glick Jun 25 '19 at 14:07
11

If your system has access to NodeJS you could install the following Node package, strip-ansi-cli.

$ npm install -g strip-ansi-cli

You can then run your command like so:

$ command-that-produces-colored-output | strip-ansi > outfile
David McNamara
  • 111
  • 1
  • 2
  • 3
    NodeJS is a huge dependency, when there are solutions that can use languages and tools already present in most systems. – user137369 Nov 14 '17 at 16:50
  • Also, this is the slowest solution listed (see [here](http://blog.vmchale.com/article/strip-benchmarks)) and you probably *will* notice the difference. –  Nov 17 '17 at 08:23
  • It's worth noting that all this module does is replaces all matches of the regex `string.replace(ansiRegex(), '')` which is defined here https://github.com/chalk/ansi-regex/blob/main/index.js. – Andy Jun 13 '21 at 02:23
4
$ command-that-produces-colored-output | ansifilter

... and if necessary, (dnf, ...) install ansifilter

JJoao
  • 11,887
  • 1
  • 22
  • 44
3

This sed command did it for me:

sed -r "s/\\^\\[(\\[[^@-~]+[@-~]|[0-9@-_]|%@)//g"

Example:

$ command-that-produces-colored-output | sed -r "s/\\^\\[(\\[[^@-~]+[@-~]|[0-9@-_]|%@)//g" > outfile
Ben
  • 131
  • 2
3

You can use ac for this. It should be faster than anything listed above (though perl and sed should be decent). Here's an example:

curl -s wttr.in/LA | ac -s

As a disclaimer: the color filtering functionality was written by me.

Jeff Schaller
  • 66,199
  • 35
  • 114
  • 250