用于 Semver 匹配的 GNU grep 正则表达式
GNU grep regex for Semver matching
我有一个 URL,我正在尝试提取 Semver 的一部分。 Semver 的格式为 2.x.0
(如果有帮助,它将始终为 2.x.0)。我需要 x 值,在我的例子中它是 15290
.
我正在使用 GNU grep。这是我目前所拥有的:
$echo "https://example.com/repository/local/foo-bar/2.15290.0/foo_bar-2.15290.0.tar.gz" | grep -oP '(?<=[.])\d+(?=[.0])'
(?<=[.]) is a look behind. It matches, in this case, just after a period.
\d+ matches any number of digits characters.
(?=[.0]) is a look ahead. It matches, in this case, just before a period 0.
我得到的输出是
15290
15290
0
我认为 0 匹配是因为 foo_bar-2.15290.0.tar.gz
。有更好的方法吗?不知道我的逻辑对不对
您可以扩展环视以使其更具体并匹配例如以下 /
(?<=\d[.])\d+(?=\.\d+/)
echo "https://example.com/repository/local/foo-bar/2.15290.0/foo_bar-2.15290.0.tar.gz" | grep -oP '(?<=\d[.])\d+(?=\.\d+/)'
输出
15290
如果 /
并不总是存在,您还可以声明一个 .
和右边的数字,而不是后面再跟一个 .
(?<=\d[.])\d+(?=\.\d+(?!\.))
您的正则表达式 (?<=[.])\d+(?=[.0])
匹配任何一个或多个以点开头并后跟点或 0
的数字。因此,字符串的 2.15290.0/foo_bar-2.15290.0.
部分具有三个有效匹配项,15290
、15290
和 0
.
你可以使用
grep -oP '.*2\.\K\d+(?=\.0\b)' <<< "https://example.com/repository/local/foo-bar/2.15290.0/foo_bar-2.15290.0.tar.gz"
见regex demo and the online grep
demo。 详情:
.*
- 除换行字符外的任何零个或多个字符,尽可能多(这使得 grep
return 最后一次出现匹配项)
2\.
- 2.
字符串
\K
- 匹配重置运算符丢弃目前匹配的文本
\d+
- 一位或多位数字
(?=\.0\b)
- 要求 .0
后没有字符字符立即出现在当前位置右侧的前瞻。
以防万一你想使用 awk
:
url="https://example.com/repository/local/foo-bar/2.15290.0/foo_bar-2.15290.0.tar.gz"
awk 'match([=11=],/2\.[0-9]+\.0/){print substr([=11=],RSTART+2,RLENGTH-4)}' <<< "$url"
见online demo。找到 2\.[0-9]+\.0
模式并从第三个字符减去最后两个字符打印它的一部分。
第一个解决方案: 使用您显示的示例,您可以尝试遵循 awk
。只需根据显示的示例将字段分隔符设置为 /|\.tar|-
,然后打印倒数第二列。
echo "https://example.com/repository/local/foo-bar/2.15290.0/foo_bar-2.15290.0.tar.gz" |
awk -F'/|\.tar|-' '{print $(NF-3)}'
第二个解决方案: 以更有效的方式使用 match
函数,其他答案的匹配可能会失败,因为那是 运行 在整行上,以防在同一行上找到更多匹配项,但这将在现场显示样本。
echo "https://example.com/repository/local/foo-bar/2.15290.0/foo_bar-2.15290.0.tar.gz" |
awk -F'/' 'match($NF,/-[0-9]+\.[0-9]+\.[0-9]+\.tar\.gz/){print substr($NF,RSTART+3,RLENGTH-12)}'
第三个解决方案: 在这里使用 GNU grep
,它将专门查找路径的最后一个值并打印版本按照它。
echo "https://example.com/repository/local/foo-bar/2.15290.0/foo_bar-2.15290.0.tar.gz" |
grep -oP '.*/.*?-\d+\.\K\d+(?=\.\d+)'
我有一个 URL,我正在尝试提取 Semver 的一部分。 Semver 的格式为 2.x.0
(如果有帮助,它将始终为 2.x.0)。我需要 x 值,在我的例子中它是 15290
.
我正在使用 GNU grep。这是我目前所拥有的:
$echo "https://example.com/repository/local/foo-bar/2.15290.0/foo_bar-2.15290.0.tar.gz" | grep -oP '(?<=[.])\d+(?=[.0])'
(?<=[.]) is a look behind. It matches, in this case, just after a period.
\d+ matches any number of digits characters.
(?=[.0]) is a look ahead. It matches, in this case, just before a period 0.
我得到的输出是
15290
15290
0
我认为 0 匹配是因为 foo_bar-2.15290.0.tar.gz
。有更好的方法吗?不知道我的逻辑对不对
您可以扩展环视以使其更具体并匹配例如以下 /
(?<=\d[.])\d+(?=\.\d+/)
echo "https://example.com/repository/local/foo-bar/2.15290.0/foo_bar-2.15290.0.tar.gz" | grep -oP '(?<=\d[.])\d+(?=\.\d+/)'
输出
15290
如果 /
并不总是存在,您还可以声明一个 .
和右边的数字,而不是后面再跟一个 .
(?<=\d[.])\d+(?=\.\d+(?!\.))
您的正则表达式 (?<=[.])\d+(?=[.0])
匹配任何一个或多个以点开头并后跟点或 0
的数字。因此,字符串的 2.15290.0/foo_bar-2.15290.0.
部分具有三个有效匹配项,15290
、15290
和 0
.
你可以使用
grep -oP '.*2\.\K\d+(?=\.0\b)' <<< "https://example.com/repository/local/foo-bar/2.15290.0/foo_bar-2.15290.0.tar.gz"
见regex demo and the online grep
demo。 详情:
.*
- 除换行字符外的任何零个或多个字符,尽可能多(这使得grep
return 最后一次出现匹配项)2\.
-2.
字符串\K
- 匹配重置运算符丢弃目前匹配的文本\d+
- 一位或多位数字(?=\.0\b)
- 要求.0
后没有字符字符立即出现在当前位置右侧的前瞻。
以防万一你想使用 awk
:
url="https://example.com/repository/local/foo-bar/2.15290.0/foo_bar-2.15290.0.tar.gz"
awk 'match([=11=],/2\.[0-9]+\.0/){print substr([=11=],RSTART+2,RLENGTH-4)}' <<< "$url"
见online demo。找到 2\.[0-9]+\.0
模式并从第三个字符减去最后两个字符打印它的一部分。
第一个解决方案: 使用您显示的示例,您可以尝试遵循 awk
。只需根据显示的示例将字段分隔符设置为 /|\.tar|-
,然后打印倒数第二列。
echo "https://example.com/repository/local/foo-bar/2.15290.0/foo_bar-2.15290.0.tar.gz" |
awk -F'/|\.tar|-' '{print $(NF-3)}'
第二个解决方案: 以更有效的方式使用 match
函数,其他答案的匹配可能会失败,因为那是 运行 在整行上,以防在同一行上找到更多匹配项,但这将在现场显示样本。
echo "https://example.com/repository/local/foo-bar/2.15290.0/foo_bar-2.15290.0.tar.gz" |
awk -F'/' 'match($NF,/-[0-9]+\.[0-9]+\.[0-9]+\.tar\.gz/){print substr($NF,RSTART+3,RLENGTH-12)}'
第三个解决方案: 在这里使用 GNU grep
,它将专门查找路径的最后一个值并打印版本按照它。
echo "https://example.com/repository/local/foo-bar/2.15290.0/foo_bar-2.15290.0.tar.gz" |
grep -oP '.*/.*?-\d+\.\K\d+(?=\.\d+)'