背景
我正在尝试使用单独的文件和函数编写一个像样的bash解析器:
- 参数解析(例如,确定要做什么)
- 解析参数处理(例如,执行这些操作)
- 打印CLI用法。
然而,当我试图将“POSITIONAL_ARGS”传递到parse_args() {
时,参数似乎没有到达。
示例:
假设我在目录中有以下main.sh
文件:/src
:
#!/bin/bash
POSITIONAL_ARGS=()
# source arg_parser.sh
source src/arg_parser/arg_parser.sh
source src/arg_parser/print_usage.sh
# print the usage if no arguments are given
[ $# -eq 0 ] && { print_usage; exit 1; }
echo "POSITIONAL_ARGS=$POSITIONAL_ARGS"
parse_args "$POSITIONAL_ARGS"
下面的arg_parser.sh
文件:src/arg_parser/arg_parser.sh
:
#!/bin/bash
parse_args() {
local positional_args="$1"
# Specify default argument values.
local apply_certs_flag='false'
local check_http_flag='false'
local check_https_flag='false'
local generate_certs_flag='false'
local project_name_flag='false'
local port_flag='false'
while [[ $# -gt 0 ]]; do
echo "dollar1=$1"
echo "positional_args=$positional_args"
echo "dollar hashtag=$#"
case $1 in
-a|--apply-certs)
apply_certs_flag='true'
shift # past argument
;;
-ch|--check-http)
check_http_flag='true'
shift # past argument
;;
-cs|--check-https)
check_https_flag='true'
shift # past argument
;;
-g|--generate-certs)
generate_certs_flag='true'
shift # past argument
;;
-n|--project-name)
project_name_flag='true'
project_name="$2"
assert_is_non_empty_string "${project_name}"
shift # past argument
shift
;;
-p|--port)
port_flag='true'
port="$2"
assert_is_non_empty_string "${project_name}"
shift # past argument
shift
;;
-*)
echo "Unknown option $1"
print_usage
exit 1
;;
esac
done
set -- "${POSITIONAL_ARGS[@]}" # restore positional parameters
}
预期输出
当我运行./src/main.sh -a
时,我会期望输出:
echo "POSITIONAL_ARGS=-a
dollar1=-a
positional_args=-a
dollar_hashtag=1
dollar1=-a
positional_args=-a
dollar_hashtag=0
输出
然而,实际的输出是一个无限循环,而不是解析/吃/转移参数:
dollar1=
positional_args=
dollar hashtag=1
dollar1=
positional_args=
dollar hashtag=1
dollar1=
positional_args=
dollar hashtag=1
.... etc.
提问
如何将CLI中的参数从src/main.sh
传递到文件src/arg_parser/arg_parser.sh
中的parse_args()
函数中,以便可以解析它们?
注意事项
我以前有
-p|--prereq)
prerequistes_only_flag='true'
shift # past argument
;;
-*|--*)
echo "Unknown option $1"
print_usage
exit 1
;;
*)
POSITIONAL_ARGS+=("$1") # save positional arg
shift # past argument
;;
esac
然而,shellcheck说--*)
将永远不会到达,因为-*|
。
假设
我认为至少有一个错误可能是我在最初的问题中将POSITIONAL_ARGS
视为字符串而不是数组。然而,shellcheck告诉我它是一个数组:
In src/main.sh line 26:
echo "POSITIONAL_ARGS=$POSITIONAL_ARGS"
^--------------^ SC2128 (warning): Expanding an array without an index only gives the first element.
1条答案
按热度按时间oxosxuxt1#
问题
POSITIONAL_ARGS
包含了位置参数。POSITIONAL_ARGS
当作变量而不是数组。缺失信息:
$@
将传入的参数作为数组给出。$#
给出了传入参数的长度/数量。解决方案
找到了以下
src/main.sh
含量的解决方案:以及附带的
src/arg_parser/arg_parser.sh
文件内容:改进空间
可以看到,我删除了
positional_args
的使用,而是使用了隐式数组$@
和数组长度$#
。我认为这个解决方案可以通过将$@
与positional_args
交换来改进,以使其更具可读性。此交换中的一个问题是shift
命令会吃掉传入数组$@
中的第一个元素,而不是local positional_args
数组中的第一个元素。因此,要解决这个问题,可以更改
shift
参数以吃掉local positional_args
数组中的第一个元素。