Bash 4.2.46 getopts concatenated short options 并在处理过程中重置 OPTIND 导致无限循环:如何在 Bash 中解决这个问题?
Bash 4.2.46 getopts concatenated short options and resetting OPTIND during processing leads to an infinite loop: How can this be remedied in Bash?
我在最新的 CentOS 7 VM 中使用以下 Bash 版本:
GNU bash, version 4.2.46(2)-release (x86_64-redhat-linux-gnu)
以下代码按预期执行(注意 -x -y):
set -- -x -y; OPTIND=1; while getopts xy opt; do echo $opt; OPTIND=$OPTIND; done
x
y
但是,当我将两个短选项组合到 -xy 时,会发生无限循环:
set -- -xy; OPTIND=1; while getopts xy opt; do echo $opt; OPTIND=$OPTIND; done
x
x
x ... infinite output
触发器是 OPTIND=$OPTIND
赋值。如果将其删除,则不会发生该行为。感觉好像有一些隐藏的子字符串索引正在进行:
-xy
不仅仅是索引 </code>,<code>OPTIND
可以描述为单个整数
- x
的索引 ${1:1:1}
- 和
${1:2:1}
为y
也许这些是由手册页中未描述的其他 getopts 参数指示的。在编写包装器以允许部分 argument/nested getopts 处理时,任何人都可以阐明这一点,这可能会帮助我解决这个问题吗?
出于好奇:我已经为嵌套的 getopts 处理实现了一些包装函数。这些允许对参数进行部分处理,在此期间可能会调用函数,这些函数也使用包装函数进行 getopts 处理。我将 OPTIND
值保存在堆栈数组变量中,当一个值从嵌套中弹出时,OPTIND
需要重置。除了使用连接的短标志参数的情况外,一切都很好。 (该实现还使指定长选项成为可能。)
How can this be remedied in Bash?
好吧,通过修补源代码。但我不想这样做,我相信现在的行为是正确的。
您可以向 getopt.c
添加一个附加函数,并通过 variables.c
中的一些特殊变量公开它,这将允许操纵 getopts
内部状态。
或更简单 - 我看到 getopts.def 可加载内置程序,您可以修补它以向 serialize/deserialize getopts 状态添加一些附加选项。
您还可以提供自己的 getopts
实现作为 bash 函数,具有自定义语义和自定义状态 serializer/deserializer。
Can anyone shed any light on
来自 posix getopts:
If the application sets OPTIND to the value 1, a new set of parameters can be used: either the current positional parameters or new arg values. Any other attempt to invoke getopts multiple times in a single shell execution environment with parameters (positional parameters or arg operands) that are not the same in all invocations, or with an OPTIND value modified to be a value other than 1, produces unspecified results.
据我们所知:
- setting OPTIND=1 resets the internal state of getopt ()
- 未指定 如果您修改
OPTIND
. 会发生什么
您看到的行为已记录 - 将 OPTIND=1
设置为 $OPTIND
等于 1
重置 getopt()
,这会导致无限循环,正如人们所期望的那样.除此之外,bash 文档没有指定当您修改 OPTIND
时应该发生什么。不要做。您认为将 OPTIND
设置为自定义值会以特定方式影响 getopts
的期望没有任何根据。不会的。
resolve this one issue when writing my wrapper to allow for partial argument/nested getopts handling?
如果您正在编写自己的参数解析模块,请不要使用 getopts
并且不要依赖于未定义、未指定或实现定义的行为。我建议以与 GNU getopt
相同的方式来做 - 在单独的子进程中生成 shell 源代码字符串,而不是依赖全局变量 OPT*
并贡献意大利面条代码。
不要嵌套getopts
,它不可重入,无法影响它的内部状态,它使用全局变量。 getopts
sets OPTIND
,不需要读,除非OPTIND
重新设置为1
,在哪种情况 getopts
被重置。任何其他值都可能被忽略。一个接一个地叫getopts
就可以了。
我在最新的 CentOS 7 VM 中使用以下 Bash 版本:
GNU bash, version 4.2.46(2)-release (x86_64-redhat-linux-gnu)
以下代码按预期执行(注意 -x -y):
set -- -x -y; OPTIND=1; while getopts xy opt; do echo $opt; OPTIND=$OPTIND; done
x
y
但是,当我将两个短选项组合到 -xy 时,会发生无限循环:
set -- -xy; OPTIND=1; while getopts xy opt; do echo $opt; OPTIND=$OPTIND; done
x
x
x ... infinite output
触发器是 OPTIND=$OPTIND
赋值。如果将其删除,则不会发生该行为。感觉好像有一些隐藏的子字符串索引正在进行:
-xy
不仅仅是索引</code>,<code>OPTIND
可以描述为单个整数- x 的索引
- 和
${1:2:1}
为y
${1:1:1}
也许这些是由手册页中未描述的其他 getopts 参数指示的。在编写包装器以允许部分 argument/nested getopts 处理时,任何人都可以阐明这一点,这可能会帮助我解决这个问题吗?
出于好奇:我已经为嵌套的 getopts 处理实现了一些包装函数。这些允许对参数进行部分处理,在此期间可能会调用函数,这些函数也使用包装函数进行 getopts 处理。我将 OPTIND
值保存在堆栈数组变量中,当一个值从嵌套中弹出时,OPTIND
需要重置。除了使用连接的短标志参数的情况外,一切都很好。 (该实现还使指定长选项成为可能。)
How can this be remedied in Bash?
好吧,通过修补源代码。但我不想这样做,我相信现在的行为是正确的。
您可以向 getopt.c
添加一个附加函数,并通过 variables.c
中的一些特殊变量公开它,这将允许操纵 getopts
内部状态。
或更简单 - 我看到 getopts.def 可加载内置程序,您可以修补它以向 serialize/deserialize getopts 状态添加一些附加选项。
您还可以提供自己的 getopts
实现作为 bash 函数,具有自定义语义和自定义状态 serializer/deserializer。
Can anyone shed any light on
来自 posix getopts:
If the application sets OPTIND to the value 1, a new set of parameters can be used: either the current positional parameters or new arg values. Any other attempt to invoke getopts multiple times in a single shell execution environment with parameters (positional parameters or arg operands) that are not the same in all invocations, or with an OPTIND value modified to be a value other than 1, produces unspecified results.
据我们所知:
- setting OPTIND=1 resets the internal state of getopt ()
- 未指定 如果您修改
OPTIND
. 会发生什么
您看到的行为已记录 - 将 OPTIND=1
设置为 $OPTIND
等于 1
重置 getopt()
,这会导致无限循环,正如人们所期望的那样.除此之外,bash 文档没有指定当您修改 OPTIND
时应该发生什么。不要做。您认为将 OPTIND
设置为自定义值会以特定方式影响 getopts
的期望没有任何根据。不会的。
resolve this one issue when writing my wrapper to allow for partial argument/nested getopts handling?
如果您正在编写自己的参数解析模块,请不要使用 getopts
并且不要依赖于未定义、未指定或实现定义的行为。我建议以与 GNU getopt
相同的方式来做 - 在单独的子进程中生成 shell 源代码字符串,而不是依赖全局变量 OPT*
并贡献意大利面条代码。
不要嵌套getopts
,它不可重入,无法影响它的内部状态,它使用全局变量。 getopts
sets OPTIND
,不需要读,除非OPTIND
重新设置为1
,在哪种情况 getopts
被重置。任何其他值都可能被忽略。一个接一个地叫getopts
就可以了。