0

How do I capture/escape # in a test? I'm trying to use the clever answer from How to reference captures in bash regex replacement to color everything after a # green

foo='hello # world'
foo="$([[ $foo =~ (#.*) ]] && echo -e ${foo/$BASH_REMATCH/\\e[32m${BASH_REMATCH[1]}\\e[0m} || echo $foo)"
echo -e $foo

I have tried using (#.*), (\#.*), and (\\#.*). The first two apparently successfully test hello # world, but don't replace it correctly...?

[[ $foo =~ (#.+) ]] && echo -e "${foo/$BASH_REMATCH/! ${BASH_REMATCH[1]} !}"
# prints: hello # world

[[ $foo =~ ( #.+) ]] && echo -e "${foo/$BASH_REMATCH/! ${BASH_REMATCH[1]} !}"
# prints: hello!  # world !

As seen above, if I precede the # with a space, it works fine, but I want a generic solution, and lookbehinds don't appear to work.

I can get this to work using sed, but for my purposes, it's very slow (on the order of seconds). I'm sure there's a faster way that I could do this using sed, but I'd really like a vanilla bash solution.

dx_over_dt
  • 13,240
  • 17
  • 54
  • 102

2 Answers2

2
foo='hello # world'
esc_start=$'\e[32m'
esc_end=$'\e[0m'
 
if [[ $foo =~ (#.*) ]]; then
  foo="${foo/"$BASH_REMATCH"/"${esc_start}${BASH_REMATCH}${esc_end}"}"
fi
Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
0

Maybe consider replacing bash-native text replacement with sed which is more suitable for complex strings.

foo="hello # world" char='#' foo=$([[ $foo =~ (($char).*) ]] && echo -e $( echo $foo | sed "s/$BASH_REMATCH/\\\\e[32m${BASH_REMATCH[1]}\\\\e[0m/") || echo $foo); echo -e $foo
  • 1
    There's a major performance impact that comes with using `sed` here: It's faster once it's running, but _much_ slower to start up; starting a copy of `sed` just to process a single line is basically always counterproductive. – Charles Duffy Oct 26 '20 at 19:18
  • Also, note that `echo -e $foo` is several flavors of buggy. `echo -e "$foo"` is unreliable -- its behavior can be modified by both compile-time and runtime configuration, which is not true of the POSIX-compliant equivalent `printf '%b\n' "$foo"` -- and `echo -e $foo` additionally has the bugs described in [I just assigned a variable, but `echo $variable` shows something else!](https://stackoverflow.com/questions/29378566/i-just-assigned-a-variable-but-echo-variable-shows-something-else) – Charles Duffy Oct 26 '20 at 19:20
  • ...for more details on the `printf`-vs-`echo` thing, see the excellent answer to [Why is printf better than echo?](https://unix.stackexchange.com/a/65819/3113) over at [unix.se]. – Charles Duffy Oct 26 '20 at 19:21