milks
milks

Reputation: 314

Bash regex: replace string with any number of characters

I'm trying to remove colouring codes from a string; e.g. from: \033[36;1mDISK\033[0m to: DISK

my regex looks like this: \033.*?m so match '\033' followed by any number of chars, terminated by 'm'

when I search for the pattern, it finds a match; [[ "$var" =~ $regex ]] evaluates to true

however when I try to replace matches, nothing happens and the same string is returned.

Here's my complete script:

regex="\033.*?m"
var="\033[36;1mDISK\033[0m"

if [[ "$var" =~ $regex ]]
then
        echo "matches"
        echo ${var//$regex}
else
        echo "doesn't match!"
fi

The problem appears to be with the match any number of any character part of the regex. I can successfully replace DISK but if I change that to D.*K or D.*?K it fails.

Note in all above cases the pattern claims to match the string but fails when replacing. Not too sure where to go with this now, any help appreciated.

Thanks

Upvotes: 1

Views: 5184

Answers (2)

chepner
chepner

Reputation: 531858

To use the parameter expansion substitution operator, you need to use an extended glob.

shopt -s extglob
newvar=${var//\\033\[*([0-9;])m}

To break it down:

  • \\033\[ - match the encoded escape character and [.
  • *([0-9;]) - match zero or more digits or semicolons. You could use +([0-9;]) to (more correctly?) match one or more digits or semicolons
  • m - the trailing m.

Upvotes: 1

devnull
devnull

Reputation: 123608

The following should do it:

$ var="\033[36;1mDISK\033[0m"
$ newvar=$(printf ${var} | sed -r "s/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]//g")
$ echo ${newvar}

returns:

DISK

Now verify!

$ echo $var | od
0000000 030134 031463 031533 035466 066461 044504 045523 030134
0000020 031463 030133 005155
0000026
$ echo $newvar | od
0000000 044504 045523 000012
0000005

Upvotes: 1

Related Questions