我有 bash 脚本,我只想支持长选项(“--option”)。 --option 可以选择包含一个或多个参数。直到但不包括第一个“--”或命令行字符串末尾的所有单词(任何由空格分隔的内容)都被视为“--option-arguments”。结果中的尾随空格是可以的。由于每个可能的选项都会被其他函数调用,因此需要最大的性能。因此,尽量避免 bash 循环和外部命令。
与“第一次出现”问题斗争了很多小时,直到我发现这个答案这提醒我 POSIX(以及 bash)不支持非贪婪/惰性正则表达式运算符。
该怎么办?
答案1
您无法按照您想要的方式使用正则表达式解析选项,因为选项不是以字符串形式传递,而是以列表字符串。myscript --option foo bar -- qux
有myscript
, --option
, foo
, bar
,--
和qux
作为单独的参数,它们都不包含空格。
循环是 bash 中的方法。
case "$1" in
--option1)
shift
while [[ $# -ne 0 && "$1" != "--" ]]; do
option1_args+=("$1")
shift
done
(($# == 0)) || shift
done
如果性能是一个大问题,那么您就不应该使用 bash。尝试使用 ksh — 它是免费的,几乎可以在任何地方使用,即使它没有默认安装,而且它通常比 bash 快得多。如果这仍然太慢,您需要一种更高级的编程语言,例如 Perl、Python 或 Ruby。
答案2
发现这个相当简单的解决方案......
function optionArg () {
local _find="$1"; shift 1
local _optarg=""
local _reBeg=""
#
_reBeg="${_find}"'[= ]+(.*?)( --)?'
### no regex nongreedy operator support in POSIX
### will have to just truncate after first match
#
if [[ "$*" =~ $_reBeg ]]
then
_optarg="${BASH_REMATCH[1]}"
### all arguments following --option[= ]
#
_optarg="${_optarg%%--*}"
### limit to just arguments up to next --option (no lazy support in POSIX)
#
return 0
else
return 1
fi
给定一个带有选项的脚本或函数调用,后跟其他选项,例如......
otherfunction --option1 arg1 arg2 --option2 -- file1 /home/me/file2
对于 otherfunction() 接受的每个选项, optionArg() 将被调用,就像......
_optarg1="$(optionArg --option1 "$@")"
_optarg2="$(optionArg --option2 "$@")"
_optarg3="$(optionArg -- "$@")"
结果将是...
_optarg1="arg1 arg2 "
_optarg2=""
_optarg3="file1 /home/me/file2"