2 个版本
0.1.1 | 2024 年 4 月 11 日 |
---|---|
0.1.0 | 2024 年 4 月 11 日 |
在 命令行工具 中排名 391
每月下载量 95
63KB
1K SLoC
ArgParse-sh
用于解析 shell 脚本参数并提供结果作为环境变量的工具。
安装
Cargo 安装
首选的安装方法使用 cargo
,Rust 工具。如果您在本地机器上安装了 Rust,请运行
cargo install argparse-sh
二进制文件将被构建并放入您的 ~/.cargo/bin/
文件夹中。将其添加到您的 PATH
或直接引用,您就设置好了。
从源代码构建
您可以从源代码下载和构建应用程序。这同样需要您在本地机器上安装 Rust 以及 Git。要这样做,请运行
git clone [email protected]:Hounshell/argparse-sh.git
cd argparse-sh
cargo build --release
编译后的二进制文件将在 target/release/argparse-sh
。将此文件放在您喜欢的位置,并将其添加到您的 PATH
或直接引用。
使用方法
ArgParse-sh 接受两组参数。第一组定义所有要解析的参数。第二组是要解析的参数。这最好通过一个简单的示例来说明
$ argparse-sh --string text -- --text "Hello, world!"
TEXT="Hello, world!"
这做了什么?它定义了一组参数(一个名为 "text" 的字符串参数)然后解析了一组参数值。输出是一个设置提供参数的环境变量的脚本。
这是一个简单的示例,但不是很实用。相反,让我们将其放入一个脚本中,并通过脚本将参数传递给 ArgParse-sh
demo.sh
eval "$(argparse-sh --string text -- "$@")";
echo "$TEXT"
让我们把这个脚本拆分成几个部分
-
argparse-sh
- 这将调用 ArgParse-sh 程序 -
--string text
- 这表示 ArgParse-sh 可以接受一个名为 "text" 的可选参数。值是字符串,没有默认值。 -
--
- 这表示 ArgParse-sh 我们已经完成了参数的定义。所有剩余的命令行参数都应该被视为参数值。 -
"$@"
- 将脚本调用时传递的所有参数转发到ArgParse-sh。因为这在--
之后,ArgParse-sh将解释这些参数。 -
eval "$(...)";
- ArgParse-sh的输出是脚本命令。eval
在当前shell中执行这些命令。 -
echo "$TEXT"
- ArgParse-sh将输出的脚本命令设置环境变量为参数的值。这将打印传递给"text"参数的值。
如果我们运行demo.sh
,我们可以看到这一切都在行动中。
$ ./demo.sh --text "Hello, world!"
Hello, world!
ArgParse-sh识别--text
参数并期望一个字符串。这个字符串("Hello, world!")被写入名为"TEXT"的环境变量中(根据参数的名称),然后可以被脚本的其他部分使用。
在下面的几个示例中,我们将省略argparse-sh命令中的eval
部分。这将导致ArgParse-sh的输出直接显示在屏幕上,让我们更清楚地看到发生了什么。
参数类型
支持几种参数类型。通常它们共享相同的一组选项(当这样做有意义时),并且一些具有额外的选项或形式。
常见参数参数
定义参数有一个常见的模式,以及一些可以提供的常见参数。
--<type> [<name / key 1> <key 2> <key 3> ...]
要开始定义一个参数,我们需要指定参数类型。在类型之后,我们可以提供用于提供此参数的名称和键的缩写。这个缩写涵盖了最常见的案例,但您不必使用它;名称和标志可以单独定义。
可用的类型有
- --boolean 或 --bool - "true"或"false"值。
- --choice 或 --pick - 从选项列表中选择一个。
- --float 或 --number - 64位浮点数。
- --integer 或 --int - 64位有符号整数。
- --string 或 --str - 自由文本。
示例
$ argparse-sh --string given-name first-name name -- --first-name "Alice"
GIVEN_NAME="Alice"
这创建了一个名为"GIVEN_NAME"的单个字符串参数,可以使用--given-name
、--first-name
或--name
设置。这是缩写形式
$ argparse-sh --string --name GIVEN_NAME \
--flag "--given-name" \
--flag "--first-name" \
--flag "--name" \
-- --first-name "Alice"
GIVEN_NAME="Alice"
--name <name>
提供要存储此参数值的环境变量的名称。
如果没有提供名称,则将使用定义的第一个标志(使用--flag或上述缩写)。规范化删除任何前导或尾随的非字母数字字符。所有其他非字母数字序列都将替换为"_",整个字符串将大写。例如,如果第一个标志是"--first-name",则规范化的名称将是"FIRST_NAME"。
示例
$ argparse-sh --string name --name FIRST_NAME -- --name "Alice"
FIRST_NAME="Alice"
这将配置一个字符串参数,可以使用--name "Name"
设置,但将存储在FIRST_NAME
环境变量中。
--flag <flag>
提供一个标志,可用于指定此参数的值。该标志将原样使用,包括大小写和连字符。这是支持较短标志的好方法。您可以在没有连字符的情况下指定标志名称。
示例
$ argparse-sh --string name --flag "--first-name" --flag "-n" -- -n Alice
NAME="Alice"
这使用简写方法定义了一个名为 "NAME" 的字符串参数,但同时也定义了可用的替代标志("--first-name" 和 "-n")。
--default <默认值>
提供在未指定此参数时使用的默认值。
警告:此默认值不会被解析或验证;无效的值将被传递。
示例
$ argparse-sh --string name --default "Alice"
NAME="Alice"
如果提供了 -- --name "Bob"
,则 NAME
将设置为 "Bob",而不是 "Alice"。
--desc[ription] <描述>
提供用于在生成帮助文本时使用此参数的描述。
示例
$ eval "$(argparse-sh --string name --desc "The user's first name." --autohelp -- --help)"
OPTIONS
--name <name>
The user's first name.
我们在这个例子中使用了 eval
,因为否则很难看到输出。已为所有参数生成了帮助文本(在这种情况下仅指定了 --name
),并将帮助文本用于该参数的描述中。
--repeated
表示此参数可以重复。如果重复参数,则环境变量将设置为存在的值的数量,并且每个值都将设置为其自己的环境变量,带有基于0的索引后缀。
示例
$ argparse-sh --string name --repeated -- --name "Alice" --name "Bob" --name "Carol"
NAME="3"
NAME_0="Alice"
NAME_1="Bob"
NAME_2="Carol"
在这里,我们可以看到提供了三个名字。每个 --name
的值按顺序包含。
--required
表示此参数是必需的。如果没有提供,ArgParse-sh 将失败。
示例
$ argparse-sh --string name --required
echo ""
echo "!!! ArgParse-sh Error: Value for argument NAME is missing !!!"
echo ""
$ echo $?
2
显示错误消息,指出未提供 "name" 参数。当解析参数时出现错误时,ArgParse-sh 的退出代码为 2。
--secret
将参数标记为不在生成的帮助文本中包含。
示例
$ eval "$(target/debug/argparse-sh --string name --secret --string age --autohelp -- --help)"
OPTIONS
--age <age>
No details available.
我们再次使用 eval
以提高清晰度。请注意,为 "age" 参数生成了帮助文本,但没有为 "name" 参数生成。
--catch-all
用于标记将获取任何未识别值的参数。这对于不需要用户指定标志名称的重复参数特别有用。
请注意,捕获所有参数不需要任何标志,但建议您仍然为用户提供一些标志,以便他们可以使用 --flag=value
语法。如果不使用任何标志,则参数 必须 有一个名称。
示例
$ argparse-sh --string name --catch-all -- "Bob"
NAME="Bob"
--ordinal <顺序>
使此参数表现得像捕获所有参数,但它只会接受单个值,并且只有当没有明确提供值时。order
是一个整数,它提供了序数参数的填充顺序。下一个没有值的最低参数(例如,用户没有通过标志明确提供此参数的值)将被使用。这意味着序数可以开始于您喜欢的任何数字,并且可以在数字之间有间隔。
示例
$ argparse-sh \
--string first_name --ordinal 1 --required \
--string middle_name --ordinal 2 --required \
--string last_name --ordinal 3 --required \
-- --middle_name "Quincy" "Alice" "Smith"
FIRST_NAME="Alice"
MIDDLE_NAME="Qunicy"
LAST_NAME="Smith"
字符串参数 (--string 或 --str)
字符串参数不会对其值进行任何验证或重写。这些参数简单地传递到环境变量中。字符串参数支持所有常见的参数参数。
示例
$ argparse-sh \
--string first-name --required \
--string last-name --default "Doe" \
--string nickname --repeated --catch-all \
-- \
--first-name "John" \
--nickname "Sticky Fingers" \
--nickname "Tight Lips"
FIRST_NAME="John"
LAST_NAME="Doe"
NICKNAME="2"
NICKNAME_0="Sticky Fingers"
NICKNAME_1="Tight Lips"
整数参数 (--integer 或 --int)
整数参数会进行验证。提供的值必须可以解析为 64 位有符号整数。如果提供了无效的参数,则 argparse-sh 将失败,并显示一条消息和一个错误代码为 2。整数参数支持所有常见的参数参数。
重要:如果提供了默认值,则不会进行验证。您负责确保提供的值解析为整数,或者您的脚本能够处理非整数值。
示例
$ argparse-sh \
--integer age --required \
--integer children --default 0 \
--integer pockets --required --catch-all \
-- \
--age 42 \
7
AGE="42"
CHILDREN="0"
POCKETS="7"
浮点参数 (--float 或 --number)
浮点参数也会进行验证。提供的值必须可以解析为64位浮点数。如果提供了无效的参数,argparse-sh 将会失败并显示错误消息,错误代码为2。浮点参数支持所有常见的参数。
重要:如果提供了默认值,则不会进行验证。您负责确保提供的值解析为数字,或者您的脚本能够处理非数字值。
示例
$ argparse-sh \
--float height --required \
--float weight --default 0 \
--float cash-on-hand --catch-all \
-- \
--height 180.4 \
72.34
HEIGHT="180.4"
WEIGHT="0"
CASH_ON_HAND="72.34"
选择参数 (--choice 或 --pick)
选择参数与其他参数类型略有不同,但与字符串参数最为相似。使用选择参数时,您提供一组有效的选择和备用映射。如果提供了未识别的值,argparse-sh 将会失败并显示错误消息,错误代码为2。
重要:如果提供了默认值,则不会进行验证,也不会进行映射。您负责确保提供的值解析为您的选择之一,或者您的脚本能够处理此值。
--option <name> [<help_text>]
选择参数需要一个或多个选项参数。在 --option
之后,您必须包含选项名称。您还可以提供显示在该选项之后的帮助文本。
--map <from> <to>
将一个选项映射到另一个选项。这为具有多个名称的特定选项提供了一个简单的方法。
重要:您可以映射到不存在的选项。您负责确保映射到的选项存在。映射不是链式的;如果从 "a" 映射到 "b",从 "b" 映射到 "c",并且用户提供了 "a",则值将是 "b"。
示例
$ argparse-sh \
--choice gender --default "none" \
--option male "Person identifies as male" \
--option female "Person identifies as female" \
--map boy male \
--map girl female \
--option other "Person identifies as something else" \
--option none "Person declines to identify" \
-- \
--gender boy
GENDER="male"
$ eval "$(argparse-sh \
--choice gender --default "none" \
--option male "Person identifies as male" \
--option female "Person identifies as female" \
--map boy male \
--map girl female \
--option other "Person identifies as something else" \
--option none "Person declines to identify" \
--autohelp \
-- \
--help)"
OPTIONS
--gender <gender>
No details available.
The possible options are:
• male - Person identifies as male
• female - Person identifies as female
• boy - Identical to 'male'
• girl - Identical to 'female'
• other - Person identifies as something else
• none - Person declines to identify
When this option is not provided it will default to 'none'.
布尔参数 (--boolean 或 --bool)
布尔参数,与选择参数一样,具有额外的行为。
默认情况下,布尔参数没有值。如果用户没有指定该参数,则变量不会被设置。如果用户使用 --flag-name
提供了标志,则布尔参数的值将是 "true"。但是,用户也可以通过使用 --flag-name=false
明确指定值。用户输入仅接受 "true" 和 "false"。您可以使用 --default
标志确保它始终设置。
布尔参数不能重复,不能有顺序,也不能用作通配符。如果您尝试使用这些特性定义一个布尔参数,您将得到定义错误。
示例
$ argparse-sh --boolean happy -- --happy
HAPPY="true"
--negative-flag <flag>
布尔参数允许定义负标志。这些标志强制将值设置为 "false"。否定标志是明确定义的。
示例
$ argparse-sh --boolean happy --negative-flag "--not-happy" -- --not-happy
HAPPY="false"
这种技术与 --default
参数或 --required
参数结合使用特别有用。
$ argparse-sh --boolean happy --negative-flag "--sad" --required -- --sad
HAPPY="false"
$ argparse-sh --boolean --name "HAPPY" --negative-flag "--sad" --default "true" --
HAPPY="true"
第一行要求您包含 --happy
或 --sad
之一。如果您两者都不包含,您将得到用户错误。如果您两者都包含,您将因为 "HAPPY" 有多个值而得到错误。
第二行将 "HAPPY" 定义为默认值为 "true" 的布尔值,但可以通过包含 --sad
参数将其设置为 "false"。
其他运行时选项
在运行 argparse-sh 时,还有一些其他选项可以使用。这些选项可以放在参数列表的任何位置,但建议您将它们放在参数列表的开始或结尾。它们不能放在参数定义内部(例如,argparse-sh --bool --debug --name bad-example
是不允许的)。
--debug
通过 echo 输出调试信息。当试图确定为什么一个参数没有按预期的方式表现时,这很有用。
示例
$ eval "$(argparse-sh \
--choice gender --default "none" \
--option male "Person identifies as male" \
--option female "Person identifies as female" \
--map boy male \
--map girl female \
--option other "Person identifies as something else" \
--option none "Person declines to identify" \
--debug \
-- \
--gender boy)"
[ArgParse-sh] ArgParse-sh debugging enabled with --debug flag
[ArgParse-sh] Arguments are not exported to child processes
[ArgParse-sh]
[ArgParse-sh] Definition - type: Choice; name: GENDER; flags: gender; default: none; options: male, female, boy -> male, girl -> female, other, none
[ArgParse-sh]
[ArgParse-sh] Parsing argument values
[ArgParse-sh]
[ArgParse-sh] Parsed argument GENDER = 'male'
[ArgParse-sh]
[ArgParse-sh] Setting GENDER = "male"
[ArgParse-sh]
[ArgParse-sh] ArgParse-sh completed successfully
--auto-help
--export
--prefix <arg_prefix>
--program-name <name>
--program-summary <summary>
--program-description <description>
退出代码
-
0 - 成功
当 ArgParse-sh 成功完成时,退出代码将为 0。如果发生这种情况,您可以确信所有必需的参数都已设置,所有提供的参数都已解析,并且所有类型检查都已成功完成。
-
1 - 帮助
如果使用了
--autohelp
标志并且用户传递了--help
,则帮助文本将写入屏幕(如果设置了用户的 PAGER,则使用用户的 PAGER)并且 ArgParse-sh 将以代码 1 退出。 -
2 - 定义错误
如果参数定义存在问题,则退出代码将为 2。例如,在
--name
后没有包括参数名称将生成此错误。 -
3 - 用户错误
如果用户提供的参数存在问题,则返回此错误代码。例如,标记为必需的省略参数或为非重复参数提供多个值。
如果您在调用 argparse-sh 之前运行 set -
,则如果 ArgParse-sh 返回的退出代码不是 0,则您的脚本将自动退出。您还可以捕获此错误以更优雅地恢复。
综合起来。
这是一个使用广泛功能和最佳实践的脚本示例。
demo.sh
# Set shell to exit immediately after failed command.
set -e;
# The description is long, so we pulled it out into a variable for clarity.
PROGRAM_DESCRIPTION="This demo program provides a number of examples of how to use ArgParse-sh.
You can provide a number of arguments that are parsed and sent back to the wrapper script as
environment variables.
Feel free to save this script and run it with a variety of parameters to test things out.";
# Run ArgParse-sh with argument definitions and pass command line through.
eval "$(argparse-sh \
--string given-name first-name \
--description "Name given to you. In western cultures this is usually your first name." \
--required \
--string family-name last-name \
--description "Name inherited from your family. In western cultures this is usually your last name." \
--required \
--string nickname \
--name NICKNAMES \
--description "Nicknames that you are commonly known by." \
--repeated \
--integer age \
--description "Your age in years." \
--required \
--integer children \
--default 0 \
--secret \
--choice gender \
--description "The gender that you identify as." \
--option male "Person identifies as male" \
--map boy male \
--option female "Person identifies as female" \
--map girl female \
--option other "Person identifies as something else" \
--option none "Person declines to identify" \
--default none \
--boolean basic-data one-line single-line \
--description "Include this argument if you only want to see the first line in the output." \
--string quote \
--name QUOTES \
--description "Include one or more quotes that you find inspirational." \
--repeated \
--required \
--catch-all \
--auto-help \
--prefix "DEMO_" \
--program-name "$(basename "$0")" \
--program-summary "Sample script that uses argparse-sh to parse command line arguments." \
--program-description "$PROGRAM_DESCRIPTION" \
-- "$@")";
# Dump some of the basic variables to the screen.
echo "Hello $DEMO_GIVEN_NAME. I see you are $DEMO_AGE years old and have $DEMO_CHILDREN children.";
# We can test for existence of boolean variables
if [ "$DEMO_BASIC_DATA" = "true" ]; then
exit
fi
# We can use if statements to switch logic based on the results of a flag.
if [ "$DEMO_GENDER" = "male" ]; then
echo "You identify as male."
elif [ "$DEMO_GENDER" = "female" ]; then
echo "You identify as female."
elif [ "$DEMO_GENDER" = "other" ]; then
echo "You identify as something other than strictly male or female."
else
echo "You have declined to provide your gender identity."
fi
# We can test to see if variables are set, even for repeated arguments.
if [ -n "$DEMO_NICKNAMES" ]; then
echo ""
echo "You have $DEMO_NICKNAMES nickname(s):";
for (( i=0; i<$DEMO_NICKNAMES; i++ )); do
# We need to do this expansion to iterate over all of the values in the list.
NICKNAME=DEMO_NICKNAMES_$i
echo " ${!NICKNAME}";
done
fi
# If an argument is required you can be guaranteed that the value is set, even for repeated args.
echo ""
echo "You have $DEMO_QUOTES favorite quote(s):";
for (( i=0; i<$DEMO_QUOTES; i++ )); do
QUOTE=DEMO_QUOTES_$i
echo " ${!QUOTE}";
done
您可以使用 --help
运行此脚本以获取帮助文本
依赖关系
~2.7–4MB
~59K SLoC