Bash posix 正则表达式可选组

mik*_*ike 0 bash posix regular-expression

试图从表单类别/名称版本中的字符串中匹配一些 Gentoo 包命名组件,由于其复杂性,我得出了这样的结论:

if [[ "$1" =~ ^([<>]?=?)(([^\/]+)\/)?([^[:space:]]+)-(([[:digit:]]+)?(\.([[:digit:]]+))*([a-z])?(_(alpha|beta|pre|rc|p)([[:digit:]]*))*(-(r([[:digit:]]+))?)?)?$ ]]; then
    # use "${BASH_REMATCH[n]}" here to capture groups contents
fi
Run Code Online (Sandbox Code Playgroud)

它按照预期分割字符串<category/package-name-12345.25b_rc10-r7

Version specifier: <
Category: category
Package name: package-name
Version: 12345.25b_rc10-r7
Version, major: 12345
Version, minor: 25
Version, letter: b
Version, patch type: rc
Version, patch level: 10
Version, revision number: 7
Run Code Online (Sandbox Code Playgroud)

现在,我需要匹配和分割可能缺少版本的字符串,例如category/package-name.

那么,有没有办法让上面的版本部分可选呢?

以上,这部分内容如下:

-(([[:digit:]]+)?(\.([[:digit:]]+))*([a-z])?(_(alpha|beta|pre|rc|p)([[:digit:]]*))*(-(r([[:digit:]]+))?)?)?
Run Code Online (Sandbox Code Playgroud)

我尝试将其更改为:

(-(([[:digit:]]+)?(\.([[:digit:]]+))*([a-z])?(_(alpha|beta|pre|rc|p)([[:digit:]]*))*(-(r([[:digit:]]+)))?))?
Run Code Online (Sandbox Code Playgroud)

它适用于没有版本的字符串,但似乎可选组阻止它匹配上面这样的稍微完整的字符串,它得到:

Version specifier: 
Category: category
Package name: package-name-12345.25b_rc10-r7
Version: 
Version, major: 
Version, minor: 
Version, letter: 
Version, patch type: 
Version, patch level: 
Version, revision number:
Run Code Online (Sandbox Code Playgroud)

编辑:插槽

两个可选部件怎么样?

除上述之外,还必须匹配插槽。插槽将像这样匹配:

:(([[:digit:]]+)(\.([[:digit:]]+))*)?

现在,有一个类别/名称部分:

([<>]?=?)(([^\/]+)\/)?([^[:space:]]+)

后跟任一版本: -(([[:digit:]]+)(\.([[:digit:]]+))*)([a-z])?(_(alpha|beta|pre|rc|p)([[:digit:]]*))*(-(r([[:digit:]]+))?)?

一个槽 :(([[:digit:]]+)(\.([[:digit:]]+))*)?

或两者,版本和插槽,按此顺序。

请注意,版本以-, 作为分隔符开头,插槽以:, 作为分隔符开头。

我能想到的只有:

if [[ "$1" =~ ^${CATEGORY_PACKAGE}-${VERSION}:${SLOT}$ ]] ; then
    # use "${BASH_REMATCH[n]}" here to capture groups contents
else
    if [[ "$1" =~ ^${CATEGORY_PACKAGE}:${SLOT}$ ]] ; then
        # use "${BASH_REMATCH[n]}" here to capture groups contents
    else
        if [[ "$1" =~ ^${CATEGORY_PACKAGE}-${VERSION}$ ]] || [[ "$1" =~ ^${CATEGORY_PACKAGE}$ ]] ; then
        # use "${BASH_REMATCH[n]}" here to capture groups contents
        fi
    fi
fi
Run Code Online (Sandbox Code Playgroud)

这是一个完整的解决方案吗?有更好的版本吗?是否有基于选项的 POSIX 解决方案,例如<category-name>(<slot option>|<version option>|<version:slot> option)

编辑:

我认为 bash 可以处理一个表达式中的可选组,但我无法更改([^[:space:]:]+)以处理hyphen. 如何hyphen包含在内,因为似乎既不能作为范围中的第一个,也不能作为最后一个?

mur*_*uru 6

为了理智起见,在这种情况下,IMO 最好只使用多个正则表达式,而不是将所有可能的情况填充到单个正则表达式中:

base_package_name_regex='^([<>]?=?)(([^/]+)/)?([^[:space:]]+)'
version_regex='(([[:digit:]]+)?(\.([[:digit:]]+))*([a-z])?(_(alpha|beta|pre|rc|p)([[:digit:]]*))*(-(r([[:digit:]]+))?)?)?$ '
if [[ "$1" =~ $base_package_name_regex-$version_regex ]] || # package with version number
    [[ "$1" =~ $base_package_name_regex ]]  #  package without version number

then
    # use "${BASH_REMATCH[n]}" here to capture groups contents
fi
Run Code Online (Sandbox Code Playgroud)

另请注意,在 POSIX ERE 中,\/匹配内容未指定,并且[^\/]匹配除反斜杠或斜杠之外的任何字符。我已经删除了那些虚假的反斜杠。