3

I was digging through mysql_safe (trying to add some options) and I came across this bash scripting technique they use to assign variables from the Launch Agent: com.mysql.mysqld.plist (I'm on a mac).

Now mysqld_safe doesn't know it's being invoked by LaunchCtl, so I assume any options are converted by LaunchCtl into command line arguments, but I found this sytnax intruiging. Anyone know how this works?

I understand the basics of Case/Switch in Bash:

case "$myval" in
  switch1) do something;;
  switch2) do something;;
        *) do whatever fallthrough logic;;
esac      

with the default fall through using * In the script chunk below, the arg value is: "--basedir=" or "--datadir=" or "--pid-file=", etc But WHAT IS UP WITH THE * in there?
Is that a Regular Expression in Switch Statement?? WITH A BACKREFERENCE?

for arg do
  # the parameter after "=", or the whole $arg if no match
  val=`echo "$arg" | sed -e 's;^--[^=]*=;;'`
  # what's before "=", or the whole $arg if no match
  optname=`echo "$arg" | sed -e 's/^\(--[^=]*\)=.*$/\1/'`
  # replace "_" by "-" ; mysqld_safe must accept "_" like mysqld does.
  optname_subst=`echo "$optname" | sed 's/_/-/g'`
  arg=`echo $arg | sed "s/^$optname/$optname_subst/"`
  arg=`echo $arg | sed "s/^$optname/$optname_subst/"`
  case "$arg" in
    # these get passed explicitly to mysqld
    --basedir=*) MY_BASEDIR_VERSION="$val" ;;
    --datadir=*) DATADIR="$val" ;;
    --pid-file=*) pid_file="$val" ;;
    --plugin-dir=*) PLUGIN_DIR="$val" ;;
    --user=*) user="$val"; SET_USER=1 ;;
    ...
    ...
    *)
      if test -n "$pick_args"
      then
        append_arg_to_args "$arg"
      fi
      ;;
  esac
codeforester
  • 39,467
  • 16
  • 112
  • 140
Ashley Raiteri
  • 700
  • 8
  • 17
  • So, I realize where $val comes from: It's in the for loop: above: val=`echo "$arg" | sed -e 's;^--[^=]*=;;'` But I still don't get the * in the switches. Can you use Regular Expressions in a switch line in Bash? – Ashley Raiteri Oct 13 '11 at 18:28

2 Answers2

5

They aren't regular expressions; they're filename expansion patterns, also known as "globs".

* matches zero or more arbitrary characters, and ? matches any single character.

For more information: http://www.gnu.org/s/bash/manual/bash.html#Pattern-Matching

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
3

If you have a recent version bash, you can use real regular expressions to parse the arg, and the access the bash array BASH_REMATCH for the captured groups:

for arg; do
    if [[ $arg =~ ^--([^=]+)=(.*) ]]; then
        optname=${BASH_REMATCH[1]}
        val=${BASH_REMATCH[2]}
        optname_subst=${optname//_/-}
        case "$optname" in 
            basedir) MY_BASEDIR_VERSION="$val" ;;
            datadir) DATADIR="$val" ;;
            ...
        esac
    else
        do something with non-option argument
    fi
done
glenn jackman
  • 238,783
  • 38
  • 220
  • 352
  • I'll be a monkey's uncle. That's a nice regexp. any chance you'd break that down for me? I'm also interested in up'ing my regexp-fu. http://xkcd.com/208/ `#^ Match the beginning of the arg` `#-- literal match of typical command line argument delimiters '--option'` – Ashley Raiteri Sep 09 '15 at 20:31
  • `([^=]+)=(.*)` `Group two things seperated by one and only one '='` `[^=]+ Grab everything up until the first '=' aka, Anything Not '=' (negative lookbehind) and put it in $1` `.* Grab everthing after the '=' and put it in $2` – Ashley Raiteri Sep 09 '15 at 20:37
  • `^` : beginning of the string; `--` : two literal dashes; `(` : start of first capturing group; `[^=]` : one character that is not an equal sign (NOT negative lookbehind, it's a plain non-matching bracket expression); `+` : one or more of the preceding atom; `)` : close group; `=` : literal equal sign; `(.*)` : everything else, captured. – glenn jackman Sep 09 '15 at 21:09