jajabarr
jajabarr

Reputation: 561

sed can't replace substring with special characters

[Mac/Terminal] I'm trying to replace words in a sentence with red-colored versions of them. I'm trying to use sed, but it's not outputting the result in the format I'm expecting. i.e.

for w in ${sp}; do
    msg=`echo $msg | sed "s/$w/\\033[1;31m$w\\033[0m/g"`
done

results in:

033[1;31mstb033[0m 033[1;31mshu033[0m 033[1;31mkok033[0m

where $sp is a list of a subset of words contained in $msg

the desired output would look like:

\033[1;31mstb\033[0m \033[1;31mshu\033[0m \033[1;31mkok\033[0m

and then my hope would be that echo -e would interpret this correctly and show the red coloring instead. So far, however, I seem to not understand quite correctly how sed works in order to accomplish this.

Upvotes: 0

Views: 449

Answers (2)

tripleee
tripleee

Reputation: 189397

This seems hugely inefficient. Why do you not simply replace all the words in one go and put in the actual escape codes immediately?

sp='one two three'
msg='one little mouse, two little mice, three little mice'
echo "$msg" | sed -E "s/${sp// /|}/^[[1;31m&^[[0m/g"

Output (where I use bold to mark up the red color1):

one little mouse, two little mice, three little mice

The sed -E option is just to allow us to use a simpler regex syntax (on Linux and some other platforms, try sed -r or simply translate the script to Perl).

You would type ctrl-V esc where you see ^[ in the command line above.

If you need the message in a variable for repeated use, look at printf -v


1 Looks like Stack Overflow doesn't support <span style="color:red">, unfortunately.

Upvotes: 1

ghoti
ghoti

Reputation: 46856

What about using an array, and printf instead of echo?

$ sp="Now is the time..."
$ w=( $sp )
$ printf -v output '\e[1;31m%s\e[0m ' "${w[@]}"
$ echo "$output"
Now is the time... 

The output is obviously red, which doesn't come across here, but:

$ printf '%q\n' "$output"
$'\E[1;31mNow\E[0m \E[1;31mis\E[0m \E[1;31mthe\E[0m \E[1;31mtime...\E[0m '

And if you don't like the trailing space, you can trim it with ${output% }.

Upvotes: 1

Related Questions