shell 命名参数包含等号的Bash脚本

jhkqcmku  于 2023-03-09  发布在  Shell
关注(0)|答案(3)|浏览(204)

我尝试使用类似于以下的命名参数将一些值传递给我的bash脚本:

./script.sh --username='myusername' --password='superS3cret!' --domainou="OU=Groups with Space,OU=subou,DC=mydomain,DC=local"

下面的代码:

#!/bin/bash

while [ "$1" != "" ]; do
    PARAM=`echo $1 | awk -vFPAT='([^=]*)|("[^"]+")' -vOFS="=" '{print $1}'`
    VALUE=`echo $1 | awk -vFPAT='([^=]*)|("[^"]+")' -vOFS="=" '{print $2}'`
    case $PARAM in
        -u | --username)
            username=$VALUE
            ;;
        -p | --password)
            password=$VALUE
            ;;
        -ou | --domainou)
            domainou=$VALUE
            ;;
        *)
            echo "ERROR: unknown parameter \"$PARAM\""
            exit 1
            ;;
    esac
    shift
done

echo $username
echo "$password"
echo "$domainou"

当我运行脚本时,得到的结果是:

myusername
superS3cret!
OU

前两行是正确的,但显然我不想要OU ......我想要:

OU=Groups with Space,OU=subou,DC=mydomain,DC=local

awk似乎匹配引号内的=。我所知道的最好的解决方法是使用

-vFPAT='([^=]*)|("[^"]+")' -vOFS="="

但很明显,这是行不通的,所以我只是想知道,如果任何awk大师可以帮助我了解我的awk声明是什么问题。
谢谢布拉德

mgdq6dx1

mgdq6dx11#

你可以这样做:

#!/bin/bash

while [ $# -gt 0 ]; do
  case "$1" in
    -u=* | --username=*)
      username="${1#*=}"
      ;;
    -p=* | --password=*)
      password="${1#*=}"
      ;;
    -ou=* | --domainou=*)
      domainou="${1#*=}"
      ;;
    *)
      printf "Error: unknown option: $1\n"
      exit 1
  esac
  shift
done

printf "username: $username\n"
printf "password: $password\n"
printf "domainou: $domainou\n"
1hdlvixo

1hdlvixo2#

要解析同时包含长和短optoin的命令行选项,可以考虑使用GNU getopt,它支持长选项。虽然可以构建自己的解析器替换,但使用getopt提供了更健壮的解析:

  • 选项的缩写(例如,接受--user代替--username)。
  • 检查必需/可选值
  • 错误处理

另请参阅:Using getopts to process long and short command line options

set $(getopt --long 'username:,password:,ou:,domain:' -o 'u:p:' -- "$0" "$@")
while [ "$#" -gt 0 ] ; do
    OP=$1
    shift
    case "$OP" in
        --) PROG=$1 ; shift ; break ;;
        -u | --username) username=$1 ; shift ;;
        -p | --password) password=$1 ; shift ;;
        --ou | --domain) domainou=$1 ; shift ;;
    esac
done
# Positional arguments are set ...
kmpatx3s

kmpatx3s3#

以下是最终对我最有效的方法。
@dash-o确实让我找到了正确的方向,但你提供的脚本打印出了无关的信息:

set: usage: set [-abefhkmnptuvxBCHP] [-o option-name] [--] [arg ...]

我认为冒犯的台词是这样的:

set --long 'username:,password:,ou:,domain:' -o 'u:p:' -- "$0" "$@"

这是完成我所需要的代码。我不能把功劳归于此。我从这里偷了它Using getopts to process long and short command line options,但如果没有dash-o,我永远不会找到它,所以非常感谢!

#!/bin/bash
die() { echo "$*" >&2; exit 2; }  # complain to STDERR and exit with error
needs_arg() { if [ -z "$OPTARG" ]; then die "No arg for --$OPT option"; fi; }

while getopts u:p:o:-: OPT; do
  # support long options: https://stackoverflow.com/a/28466267/519360
  if [ "$OPT" = "-" ]; then   # long option: reformulate OPT and OPTARG
    OPT="${OPTARG%%=*}"       # extract long option name
    OPTARG="${OPTARG#$OPT}"   # extract long option argument (may be empty)
    OPTARG="${OPTARG#=}"      # if long option argument, remove assigning `=`
  fi
  case "$OPT" in
    u | username )  needs_arg; username="$OPTARG" ;;
    p | password )  needs_arg; password="$OPTARG" ;;
    o | domainou )  needs_arg; domainou="$OPTARG" ;;
    ??* )          die "Illegal option --$OPT" ;;  # bad long option
    \? )           exit 2 ;;  # bad short option (error reported via getopts)
  esac
done
shift $((OPTIND-1)) # remove parsed options and args from $@ list

echo "$username"
echo "$password"
echo "$domainou"

相关问题