1

I am trying to follow Bash Cookbook to learn about Bash Scripting. I am on example 6.8 Testing with Regular Expression.

I have the following script:

#!/usr/bin/env bash
# cookbook filename: trackmatch

for CDTRACK in *
do
     if [[ "$CDTRACK" =~ "([[:alpha:][:blank:]]*)- ([[:digit:]]*) - (.*)$" ]]
then
    echo ${BASH_REMATCH[2]}
else
    echo Error $CDTRACK
fi
done

I apply this to a couple of files in my directory:

Ludwig van Beethovern - 02 - Adagio un poco mosso.ogg

Ludwig van Beethovern - 01 - Allegro.ogg

I always get an error returned. The issue appears to be with ([[:alpha:][:blank:]]*)- ([[:digit:]]*) - section of code. When I do have the if statement as: if [[ "$CDTRACK" =~ "(.*)$" ]] then there is no error.

Any thoughts as to what I am doing wrong?

I am running the code on AWS, Bash v 4.2

4
  • try \- instead of - ? and "\s" instead of " " ? Commented May 1, 2016 at 14:42
  • Will do, but if I try ([[:ascii:]]*) it also doesn't work so I don't think that is the issue ... Commented May 1, 2016 at 14:55
  • 5
    Related: Using regex inside if clause in bash Commented May 1, 2016 at 14:59
  • 1
    This is completely irrelevant to the question, but you spelled Beethoven wrong Commented May 1, 2016 at 15:45

1 Answer 1

6

ShellCheck is a good start for bash programming. It gives quite useful hints:

Line 6:
if [[ "$CDTRACK" =~ "([[:alpha:][:blank:]]*)- ([[:digit:]]*) - (.*)$" ]]
                    ^-- SC2076: Don't quote rhs of =~, it'll match literally rather than as a regex.

Regex can't be quoted like this. Working example with escaped special characters (basically spaces):

if [[ "$CDTRACK" =~ ([[:alpha:][:blank:]]*)-\ ([[:digit:]]*)\ -\ (.*)$ ]]

or as glenn jackman proposed, quoting only the other characters (which looks weird for people using different languages, but works too):

if [[ "$CDTRACK" =~ ([[:alpha:][:blank:]]*)"- "([[:digit:]]*)" - "(.*)$ ]]

Oneliner to test against existing string:

if [[ "Ludwig van Beethovern - 02 - Adagio un poco mosso.ogg" =~ ([[:alpha:][:blank:]]*)-\ ([[:digit:]]*)\ -\ (.*)$ ]]; then echo "${BASH_REMATCH[2]}"; fi
4
  • Great answer. Alternately: ([[:alpha:][:blank:]]*)"- "([[:digit:]]*)" - "(.*)$ -- I like to use quotes for the literal bits Commented May 1, 2016 at 15:46
  • @glennjackman Thanks. Added as possible option. Learning something new every day (while forgetting other things). I can't decide which option looks more weird ... Commented May 1, 2016 at 15:51
  • Personally, I prefer quoting over backslashing. Commented May 1, 2016 at 16:16
  • reading bash cookbook led me here. i prefer escaping spaces. Commented Aug 7, 2017 at 1:24

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.