我们可以在 Bash case 语句中使用正则表达式吗?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7758704/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 00:57:55  来源:igfitidea点击:

Can we use regular expressions In Bash case statements?

bashcase-statement

提问by Ashley Raiteri

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).

我正在挖掘 mysql_safe(试图添加一些选项),我遇到了他们用来从 Launch Agent 分配变量的 bash 脚本技术:com.mysql.mysqld.plist(我在 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?

现在 mysqld_safe 不知道它正在被 LaunchCtl 调用,所以我假设 LaunchCtl 将任何选项转换为命令行参数,但我发现这个 sytnax 很有趣。有谁知道这是如何工作的?

I understand the basics of Case/Switch in Bash:

我了解 Bash 中 Case/Switch 的基础知识:

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?

默认情况下使用 * 在下面的脚本块中,arg 值为:“--basedir=”或“--datadir=”或“--pid-file=”等但是 * 在那里?
那是 Switch 语句中的正则表达式吗?? 有反向引用?

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/^\(--[^=]*\)=.*$//'`
  # 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

回答by Keith Thompson

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

它们不是正则表达式;它们是文件名扩展模式,也称为“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

更多信息:http: //www.gnu.org/s/bash/manual/bash.html#Pattern-Matching

回答by glenn Hymanman

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:

如果您有最新版本的 bash,您可以使用真正的正则表达式来解析 arg,并访问捕获组的 ba​​sh 数组 BASH_REMATCH:

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