Bash:从字符串变量的中间提取模式?
Bash: extract pattern from middle of a string variable?
我正在为命令 foo
.
编写自定义 Bash 完成函数
您可以调用 foo --help
并获得如下输出:
Usage: foo (start | stop | up | down) [options] [ARGS]
作为第一步,我希望我的完成函数解析此用法消息并获取 (
和 )
之间的元素。我想尽可能多地使用 shell 内置函数,仅在绝对必要时才生成 sed
等外部进程。现在我有:
_foo() {
local cmd= word= usage=$(foo --help) subcmds
[[ "$usage" =~ .*\((.*)\).* ]] && subcmds="${BASH_REMATCH[1]// |}"
COMPREPLY=( $(compgen -W "$subcmds" -- "$word") )
}
complete -F _foo foo
这行得通,但我想知道是否有一种方法可以在不诉诸 =~
和 BASH_REMATCH
的情况下实现相同的结果,而只是组合参数字符串操作?
我可以删除使用信息中直到开括号的部分,
"${usage#*\(}" # start | stop | up | down) [options] [ARGS]
我可以删除从右括号开始的部分,
"${usage%)*}" # Usage: foo (start | stop | up | down
但我想不出一种不引入临时变量就只提取中间部分的方法...
tmp="${usage#*\(}"
"${tmp%)*}"
我希望这样的事情能奏效,但运气不好
"${${usage#*\(}%)*}"
您可以在 BASH 替换中使用 extglob
一步完成两个替换:
tmp='Usage: foo (start | stop | up | down) [options] [ARGS]'
echo "${tmp//@(*\(|\)*)}"
@(*\(|\)*)
将匹配 glob *(
或 )*
并将其替换为空字符串。
输出:
start | stop | up | down
如果您也想剥离管道,请使用:
echo "${tmp//@(*\(|\| |\)*)}"
start stop up down
(感谢 OP)
我正在为命令 foo
.
您可以调用 foo --help
并获得如下输出:
Usage: foo (start | stop | up | down) [options] [ARGS]
作为第一步,我希望我的完成函数解析此用法消息并获取 (
和 )
之间的元素。我想尽可能多地使用 shell 内置函数,仅在绝对必要时才生成 sed
等外部进程。现在我有:
_foo() {
local cmd= word= usage=$(foo --help) subcmds
[[ "$usage" =~ .*\((.*)\).* ]] && subcmds="${BASH_REMATCH[1]// |}"
COMPREPLY=( $(compgen -W "$subcmds" -- "$word") )
}
complete -F _foo foo
这行得通,但我想知道是否有一种方法可以在不诉诸 =~
和 BASH_REMATCH
的情况下实现相同的结果,而只是组合参数字符串操作?
我可以删除使用信息中直到开括号的部分,
"${usage#*\(}" # start | stop | up | down) [options] [ARGS]
我可以删除从右括号开始的部分,
"${usage%)*}" # Usage: foo (start | stop | up | down
但我想不出一种不引入临时变量就只提取中间部分的方法...
tmp="${usage#*\(}"
"${tmp%)*}"
我希望这样的事情能奏效,但运气不好
"${${usage#*\(}%)*}"
您可以在 BASH 替换中使用 extglob
一步完成两个替换:
tmp='Usage: foo (start | stop | up | down) [options] [ARGS]'
echo "${tmp//@(*\(|\)*)}"
@(*\(|\)*)
将匹配 glob *(
或 )*
并将其替换为空字符串。
输出:
start | stop | up | down
如果您也想剥离管道,请使用:
echo "${tmp//@(*\(|\| |\)*)}"
start stop up down
(感谢 OP)