5

What is the correct way to escape a dollar sign in a bash regex? I am trying to test whether a string begins with a dollar sign. Here is my code, in which I double escape the dollar within my double quotes expression:

echo -e "AB1\nAB2\n\$EXTERNAL_REF\nAB3" | while read value;
do
    if [[ ! $value =~ "^\\$" ]];
    then
            echo $value
    else
            echo "Variable found: $value"
    fi
done

This does what I want for one box which has:

GNU bash, version 3.2.25(1)-release (x86_64-redhat-linux-gnu)

And the verbose output shows

+ [[ ! $EXTERNAL_REF =~ ^\$ ]]
+ echo 'Variable found: $EXTERNAL_REF'

However, on another box which uses

GNU bash, version 4.1.2(1)-release (x86_64-redhat-linux-gnu)

The comparison is expanded as follows

+ [[ ! $EXTERNAL_REF =~ \^\\\$ ]]
+ echo '$EXTERNAL_REF'

Is there a standard/better way to do this that will work across all implementations?

Many thanks

user1198484
  • 95
  • 2
  • 6

4 Answers4

3

Why do you use a regular expression here? A glob is enough:

#!/bin/bash

while read value; do
   if [[ "$value" != \$* ]]; then
       echo "$value"
   else
       echo "Variable found: $value"
   fi
done < <(printf "%s\n" "AB1" "AB2" '$EXTERNAL_REF' "AB3")

Works here with shopt -s compat32.

gniourf_gniourf
  • 44,650
  • 9
  • 93
  • 104
3

The regex doesn't need any quotes at all. This should work:

if [[ ! $value =~ ^\$ ]];
Ian Mackinnon
  • 13,381
  • 13
  • 51
  • 67
1

I would replace the double quotes with single quotes and remove a single \ and have the changes as below

$value =~ "^\\$"

can also be used as

$value =~ '^\$'
0

I never found the solution either, but for my purposes, I settled on the following workaround:

if [[ "$value" =~ ^(.)[[:alpha:]_][[:alnum:]_]+\\b && ${BASH_REMATCH[1]} == '$' ]]; then
    echo "Variable found: $value"
else
    echo "$value"
fi

Rather than trying to "quote" the dollar-sign, I instead match everything around it and I capture the character where the dollar-sign should be to do a direct-string comparison on. A bit of a kludge, but it works.

Alternatively, I've taken to using variables, but just for the backslash character (I don't like storing the entire regex in a variable because I find it confusing for the regex to not appear in the context where it's used):

bs="\\"
string="test\$test"
if [[ "$string" =~ $bs$ ]]; then
    echo "output \"$BASH_REMATCH\""
fi
arwild01
  • 1
  • 1