Bash:从字符串变量的中间提取模式?
我正在为commandBash:从字符串变量的中间提取模式?,bash,built-in,Bash,Built In,我正在为commandfoo编写一个自定义Bash完成函数 您可以调用foo--help并获得如下输出: Usage: foo (start | stop | up | down) [options] [ARGS] 作为第一步,我希望我的完成函数解析这个用法消息,并获取(和)之间的元素。我希望尽可能多地使用shell内置程序,仅在绝对必要时才生成外部进程,如sed。现在我有: _foo() { local cmd=$1 word=$2 usage=$(foo --help) subcmds
foo
编写一个自定义Bash完成函数
您可以调用foo--help
并获得如下输出:
Usage: foo (start | stop | up | down) [options] [ARGS]
作为第一步,我希望我的完成函数解析这个用法消息,并获取(
和)
之间的元素。我希望尽可能多地使用shell内置程序,仅在绝对必要时才生成外部进程,如sed
。现在我有:
_foo() {
local cmd=$1 word=$2 usage=$(foo --help) subcmds
[[ "$usage" =~ .*\((.*)\).* ]] && subcmds="${BASH_REMATCH[1]// |}"
COMPREPLY=( $(compgen -W "$subcmds" -- "$word") )
}
complete -F _foo foo
这是可行的,但我想知道是否有一种方法可以实现相同的结果,而不必求助于=~
和BASH\u REMATCH
,而只是结合参数字符串操作
我可以删除使用信息的一部分,直到打开页面
"${usage#*\(}" # start | stop | up | down) [options] [ARGS]
我可以从结束部分开始移除零件
"${usage%)*}" # Usage: foo (start | stop | up | down
但我想不出一种方法,在不引入临时变量的情况下,只提取中间值
tmp="${usage#*\(}"
"${tmp%)*}"
我希望这样的事情能奏效,但运气不好
"${${usage#*\(}%)*}"
您可以在BASH replacement中使用
extglob
,一步完成两个替换:
tmp='Usage: foo (start | stop | up | down) [options] [ARGS]'
echo "${tmp//@(*\(|\)*)}"
@(*\(|\)*)
将匹配glob*(
或)*
并将其替换为空字符串
输出:
start | stop | up | down
如果还希望剥离管道,请使用:
echo "${tmp//@(*\(|\| |\)*)}"
start stop up down
(感谢OP)只需介绍一下临时的。没关系。我喜欢这些路径名扩展的特殊extglob案例。这里很酷的一点是,
@
,*
或+
将给出所需的输出。很好,这真是聪明!打开extglob
似乎是在处理自定义bash完成时,这是一个好消息。我还需要去掉管道|
。这本书不容易读,但我最终得到了:“${tmp/@(*\(|\ |\)*)}”