kaspertje100
kaspertje100

Reputation: 73

bash Why doesnt my regex work?

I made this regex but it is not working.

I got this example string: ('/test/test/test/test-Test/TEST/test.sql'),

my bash code:

if [[ ${arrayQuery[$i]} =~ ([a-z0-9]+)\/([a-z0-9]+)\/([a-z0-9]+)\/([a-z0-9-]+)\/([a-z0-9]+)\/([a-z0-9]+).([a-z0-9]+) ]]; then
        queryName=$1
        echo "test $queryName"
fi

it is not priting anything can anyone explain my why this is not working?

i tried my regex on regex101.com and the regex did work on this website.

Upvotes: 3

Views: 201

Answers (5)

gniourf_gniourf
gniourf_gniourf

Reputation: 46813

From your comment it seems that you want to split the path into its components. The best option, in Bash, is to use this:

mypath=/testa/testb/testc/test-Testd/TESTe/test.sql
IFS=/ read -r -d '' -a components < <(printf '%s\0' "$mypath")

Like so, you'll have an array components that will contain each component of your path:

gniourf$ declare -p components
declare -a components='([0]="" [1]="testa" [2]="testb" [3]="testc" [4]="test-Testd" [5]="TESTe" [6]="test.sql")'

You don't need (and don't want) to use a regex for this.

Also see this question: How do I split a string on a delimiter in Bash?

Upvotes: 0

guillaume guerin
guillaume guerin

Reputation: 367

Your example does not work in regex101 with the string you provided for several reasons:

  1. Your string starts with a '/' but your regex starts with ([a-z0-9]+)
  2. Your string contains Upper case letters yet you don't use [A-Z] in your regex
  3. Your string contains a '-' yet your regex does not parse it, try adding \-
  4. You did not escape the dot replace it with '\.', by default '.' means all character

This regular expression would do the trick (link to regex101) :

\/[a-zA-Z0-9\-]+\/[a-zA-Z0-9\-]+\/[a-zA-Z0-9\-]+\/[a-zA-Z0-9\-]+\/[a-zA-Z0-9\-]+\/[a-zA-Z0-9\-]+\.[a-zA-Z0-9\-]+

I guess this string represent a SQL file in your hard drive, this regex can be shortened to :

(\/[a-zA-Z0-9\-]+)+\.sql

and does not depend on how many folders you have in your directory tree.

Upvotes: 1

chepner
chepner

Reputation: 530853

You can use [[:alnum:]] as a short cut for the (correct) class [a-zA-Z0-9] to simplify your regex while fixing it. Even simpler would be to use a parameter to shorten it:

x='[[:alnum:]]+'
# Or, if you prefer
# x='[a-zA-Z0-9]+'
if [[ ${arrayQuery[$i]} =~ ($x)/($x)/($x)/($x)/($x)/($x)\.($x) ]]; then
    queryName=$1
    echo "test $queryName"
fi

There is also an option to make regular expression matches case-insensitive, which would allow you to use your current regular expression (with a few minor fixes):

shopt -s nocasematch
if [[ ${arrayQuery[$i]} =~ ([a-z0-9]+)/([a-z0-9]+)/([a-z0-9]+)/([a-z0-9-]+)/([a-z0-9]+)/([a-z0-9]+)\.([a-z0-9]+) ]]; then
    queryName=$1
    echo "test $queryName"
fi
shopt -u nocasematch  # Turn it off again

Upvotes: 0

marek.jancuska
marek.jancuska

Reputation: 310

  • you need to escape the dot, otherwise it matches any character

  • your example string contains uppercase, but your regex only accepts lowercase letters

(edit: no quoting needed)

Upvotes: 2

reynoldsnlp
reynoldsnlp

Reputation: 1210

It should work if you add A-Z (capital letters) to all of the character sets.

Upvotes: 0

Related Questions