仅使用Bash模式匹配从字符串开头删除模式

问题描述

是否可以使用Bash的内置模式匹配和参数替换从字符串的开头 删除模式? (重击5.0.18)

给出以下数组:

myparams=( --some-param -h --15 -q 100 )

我想遍历元素并输出以下内容(从前面剥离所有-,而不会影响后面的任何内容)。所需的输出

some-param
h
15
q
100

我知道Bash Hackers Wiki - Substring removal,但是我看不到任何方法

这是一次失败的尝试,几乎有效,但是some-遭到破坏:

$ for p in "${myparams[@]}"; do echo "$p ==> ${p##*-}" ; done
--some-param ==> param
-h ==> h
--15 ==> 15
-q ==> q
100 ==> 100

另一次失败的尝试,这次some-param变成了someparam

$ for p in "${myparams[@]}"; do echo "$p ==> ${p//-}" ; done
--some-param ==> someparam
-h ==> h
--15 ==> 15
-q ==> q
100 ==> 100

这是一个可行的解决方案,但它依赖于sed(经macOS 10.15.7的sed测试):

$ for p in "${myparams[@]}"; do echo "$p ==> $(sed 's/^-*//'<<<"$p")" ; done
--some-param ==> some-param
-h ==> h
--15 ==> 15
-q ==> q
100 ==> 100

最后,这是一种使用BASH_REMATCH的有效方法-这是唯一的内置方法吗?:

$ for p in "${myparams[@]}"; do [[ $p =~ ^(-*)?(.*) ]]; echo "$p ==> ${BASH_REMATCH[2]}" ; done
--some-param ==> some-param
-h ==> h
--15 ==> 15
-q ==> q
100 ==> 100

解决方法

使用扩展模式和参数扩展:

shopt -s extglob
printf '%s\n' "${myparams[@]##+(-)}"
  • +(-)匹配一个或多个破折号
  • #仅在值的开头删除字符串
  • ##匹配可能的最长字符串
  • 使用数组作为参数会从其所有成员中删除前缀