bash - 在 Bash 中解析命令行参数的最佳方式?

标签 bash command-line getopts

经过几天的research ,我仍然无法找出在 .sh 脚本中解析 cmdline args 的最佳方法。根据我的引用资料,getopts cmd 是可行的方法,因为它“提取并检查开关而不干扰位置参数变量。意外开关或缺少参数的开关被识别并报告为错误。

位置参数(例如 2 - $@、$# 等)在涉及空格时显然不能很好地工作,但可以识别常规参数和长参数(-p 和 --longparam)。我注意到在传递带有嵌套引号的参数时,这两种方法都失败了(“这是一个 Ex. of ""quotes"".")。这三个代码示例中的哪一个最能说明处理 cmdline args 的方法?大师不推荐使用 getopt 函数,所以我尽量避免使用它!

示例 1:

#!/bin/bash
for i in "$@"
do
case $i in
    -p=*|--prefix=*)
    PREFIX=`echo $i | sed 's/[-a-zA-Z0-9]*=//'`

    ;;
    -s=*|--searchpath=*)
    SEARCHPATH=`echo $i | sed 's/[-a-zA-Z0-9]*=//'`
    ;;
    -l=*|--lib=*)
    DIR=`echo $i | sed 's/[-a-zA-Z0-9]*=//'`
    ;;
    --default)
    DEFAULT=YES
    ;;
    *)
            # unknown option
    ;;
esac
done
exit 0

示例 2:

#!/bin/bash
echo ‘number of arguments’
echo "\$#: $#"
echo ”

echo ‘using $num’
echo "\$0: $0"
if [ $# -ge 1 ];then echo "\$1: $1"; fi
if [ $# -ge 2 ];then echo "\$2: $2"; fi
if [ $# -ge 3 ];then echo "\$3: $3"; fi
if [ $# -ge 4 ];then echo "\$4: $4"; fi
if [ $# -ge 5 ];then echo "\$5: $5"; fi
echo ”

echo ‘using $@’
let i=1
for x in $@; do
echo "$i: $x"
let i=$i+1
done
echo ”

echo ‘using $*’
let i=1
for x in $*; do
echo "$i: $x"
let i=$i+1
done
echo ”

let i=1
echo ‘using shift’
while [ $# -gt 0 ]
do
echo "$i: $1"
let i=$i+1
shift
done

[/bash]

output:

bash> commandLineArguments.bash
number of arguments
$#: 0

using $num
$0: ./commandLineArguments.bash

using $@

using $*

using shift
#bash> commandLineArguments.bash  "abc def" g h i j*

示例 3:

#!/bin/bash

while getopts ":a:" opt; do
  case $opt in
    a)
      echo "-a was triggered, Parameter: $OPTARG" >&2
      ;;
    \?)
      echo "Invalid option: -$OPTARG" >&2
      exit 1
      ;;
    :)
      echo "Option -$OPTARG requires an argument." >&2
      exit 1
      ;;
  esac
done

exit 0

最佳答案

我发现使用 getopt 是最简单的。它提供了对参数的正确处理,否则这很棘手。例如,getopt 将知道如何处理在命令行上指定为 --arg=option--arg option 的长选项的参数>.

在解析传递给 shell 脚本的任何输入时有用的是使用 "$@" 变量。请参阅 bash 手册页以了解它与 $@ 的区别。它确保您可以处理包含空格的参数。

这是我如何编写脚本来解析一些简单的命令行参数的示例:

#!/bin/bash

args=$(getopt -l "searchpath:" -o "s:h" -- "$@")

eval set -- "$args"

while [ $# -ge 1 ]; do
        case "$1" in
                --)
                    # No more options left.
                    shift
                    break
                   ;;
                -s|--searchpath)
                        searchpath="$2"
                        shift
                        ;;
                -h)
                        echo "Display some help"
                        exit 0
                        ;;
        esac

        shift
done

echo "searchpath: $searchpath"
echo "remaining args: $*"

并像这样使用以表明保留了空格和引号:

user@machine:~/bin$ ./getopt_test --searchpath "File with spaces and \"quotes\"."
searchpath: File with spaces and "quotes".
remaining args: other args

关于getopt的一些基本使用信息可以引用here

关于bash - 在 Bash 中解析命令行参数的最佳方式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14786984/

相关文章:

mysql - 将 MySQL 命令行结果的输出格式更改为 CSV

c - poptGetArgs 返回 null。

bash - 如何强制 wget 跳过指向父元素的链接?

可自行编辑的 Bash 脚本

linux - 当后台进程完成时关闭前台进程

bash - 在 Bash 中使用 getopts 检索单个选项的多个参数

bash - getopts 能否解析 bash 脚本参数的一个子集,而其余部分保持不变?

java - 启动时启动java进程并在死机时自动重启

java - 如何解析 Java 中的命令行参数?

ruby - 测试纯 Ruby 程序时加载 spec.opts