gpt4 book ai didi

bash - 如何解析 Bash 中的命令行参数?

转载 作者:太空宇宙 更新时间:2023-11-04 03:35:12 24 4
gpt4 key购买 nike

假设,我有一个使用以下行调用的脚本:

./myscript -vfd ./foo/bar/someFile -o /fizz/someOtherFile

或者这个:

./myscript -v -f -d -o /fizz/someOtherFile ./foo/bar/someFile 

可接受的解析方式是什么,以便在每种情况下(或两者的某种组合)$v$f$d 都将设置为 true 并且 $outFile 将等于 /fizz/someOtherFile

最佳答案

Bash 以空格分隔(例如 --option argument )

cat >/tmp/demo-space-separated.sh <<'EOF'
#!/bin/bash

POSITIONAL_ARGS=()

while [[ $# -gt 0 ]]; do
case $1 in
-e|--extension)
EXTENSION="$2"
shift # past argument
shift # past value
;;
-s|--searchpath)
SEARCHPATH="$2"
shift # past argument
shift # past value
;;
--default)
DEFAULT=YES
shift # past argument
;;
-*|--*)
echo "Unknown option $1"
exit 1
;;
*)
POSITIONAL_ARGS+=("$1") # save positional arg
shift # past argument
;;
esac
done

set -- "${POSITIONAL_ARGS[@]}" # restore positional parameters

echo "FILE EXTENSION = ${EXTENSION}"
echo "SEARCH PATH = ${SEARCHPATH}"
echo "DEFAULT = ${DEFAULT}"
echo "Number files in SEARCH PATH with EXTENSION:" $(ls -1 "${SEARCHPATH}"/*."${EXTENSION}" | wc -l)

if [[ -n $1 ]]; then
echo "Last line of file specified as non-opt/last argument:"
tail -1 "$1"
fi
EOF

chmod +x /tmp/demo-space-separated.sh

/tmp/demo-space-separated.sh -e conf -s /etc /etc/hosts
复制粘贴上面的 block 的输出
FILE EXTENSION  = conf
SEARCH PATH = /etc
DEFAULT =
Number files in SEARCH PATH with EXTENSION: 14
Last line of file specified as non-opt/last argument:
#93.184.216.34 example.com
用法
demo-space-separated.sh -e conf -s /etc /etc/hosts
<小时/>

Bash 等于分隔(例如 --option=argument )

cat >/tmp/demo-equals-separated.sh <<'EOF'
#!/bin/bash

for i in "$@"; do
case $i in
-e=*|--extension=*)
EXTENSION="${i#*=}"
shift # past argument=value
;;
-s=*|--searchpath=*)
SEARCHPATH="${i#*=}"
shift # past argument=value
;;
--default)
DEFAULT=YES
shift # past argument with no value
;;
-*|--*)
echo "Unknown option $i"
exit 1
;;
*)
;;
esac
done

echo "FILE EXTENSION = ${EXTENSION}"
echo "SEARCH PATH = ${SEARCHPATH}"
echo "DEFAULT = ${DEFAULT}"
echo "Number files in SEARCH PATH with EXTENSION:" $(ls -1 "${SEARCHPATH}"/*."${EXTENSION}" | wc -l)

if [[ -n $1 ]]; then
echo "Last line of file specified as non-opt/last argument:"
tail -1 $1
fi
EOF

chmod +x /tmp/demo-equals-separated.sh

/tmp/demo-equals-separated.sh -e=conf -s=/etc /etc/hosts
复制粘贴上面的 block 的输出
FILE EXTENSION  = conf
SEARCH PATH = /etc
DEFAULT =
Number files in SEARCH PATH with EXTENSION: 14
Last line of file specified as non-opt/last argument:
#93.184.216.34 example.com
用法
demo-equals-separated.sh -e=conf -s=/etc /etc/hosts
<小时/>

为了更好地理解${i#*=}this guide 中搜索“子字符串删除” 。它在功能上等同于 `sed 's/[^=]*=//' <<< "$i"`它调用不必要的子进程或 `echo "$i" | sed 's/[^=]*=//'`它调用两个个不必要的子进程。

<小时/>

将 bash 与 getopt[s] 结合使用

getopt(1) 限制(较旧的、相对较新的 getopt 版本):

  • 无法处理空字符串参数
  • 无法处理嵌入空格的参数

最近的getopt版本没有这些限制。有关更多信息,请参阅这些 docs .

<小时/>

POSIX getopts

此外,POSIX shell 和其他 shell 还提供 getopts没有这些限制。我已经包含了一个简单的 getopts示例。

cat >/tmp/demo-getopts.sh <<'EOF'
#!/bin/sh

# A POSIX variable
OPTIND=1 # Reset in case getopts has been used previously in the shell.

# Initialize our own variables:
output_file=""
verbose=0

while getopts "h?vf:" opt; do
case "$opt" in
h|\?)
show_help
exit 0
;;
v) verbose=1
;;
f) output_file=$OPTARG
;;
esac
done

shift $((OPTIND-1))

[ "${1:-}" = "--" ] && shift

echo "verbose=$verbose, output_file='$output_file', Leftovers: $@"
EOF

chmod +x /tmp/demo-getopts.sh

/tmp/demo-getopts.sh -vf /etc/hosts foo bar
复制粘贴上面的 block 的输出
verbose=1, output_file='/etc/hosts', Leftovers: foo bar
用法
demo-getopts.sh -vf /etc/hosts foo bar

getopts的优点是:

  1. 它更便携,并且可以在其他 shell 中工作,例如 dash .
  2. 它可以处理多个单一选项,例如 -vf filename以典型的 Unix 方式自动进行。

getopts的缺点的问题是它只能处理短选项( -h ,而不是 --help ),而无需额外的代码。

有一个getopts tutorial它解释了所有语法和变量的含义。在bash中,还有help getopts ,这可能会提供信息。

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

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com