正则表达式匹配 SSH url 部分
Posted
技术标签:
【中文标题】正则表达式匹配 SSH url 部分【英文标题】:Regex to match SSH url parts 【发布时间】:2020-01-02 00:48:10 【问题描述】:鉴于以下 SSH 网址:
git@github.com:james/example
git@github.com:007/example
git@github.com:22/james/example
git@github.com:22/007/example
如何获取以下内容:
user@host:optional portpath (user/repo)
正如您在示例中看到的,其中一个用户名是数字而不是端口。我不知道如何解决这个问题。端口也不总是在 URL 中。
我目前的正则表达式是:
^(?P<user>[^@]+)@(?P<host>[^:\s]+)?:(?:(?P<port>\d1,5)\/)?(?P<path>[^\\].*)$
不知道还能尝试什么。
【问题讨论】:
一个小的解析器? @Jan 你的意思是不使用正则表达式来做到这一点? 看我的答案bewlo(但选择另一个较短的)。 【参考方案1】:懒惰的量词来拯救!
这似乎运作良好并且满足可选端口:
^
(?P<user>.*?)@
(?P<host>.*?):
(?:(?P<port>.*?)/)?
(?P<path>.*?/.*?)
$
换行符不是正则表达式的一部分,因为/x
修饰符已启用。如果您不使用/x
,请删除所有换行符。
https://regex101.com/r/wdE30O/5
感谢@Janoptimizations。
【讨论】:
@ThatGuy343 正确,007
出现在冒号 :
之后
@ThatGuy343 如果007
不是端口,那么哪个捕获组应该包含它?是否应该完全忽略该条目,因为它是“无效的”?我的目标是创建一个简单的解析器,而不是验证器
007 是用户名,也是路径的一部分。路径组是这样的:username/repo
@MonkeyZeus +1 我认为你很接近,但是如果 git@github.com:22/james ...它将匹配路径为 22/james,我相信什么时候应该只是 james。 ..
@MonkeyZeus: +1 但有一些优化:a)使用详细模式,b)你现在使用的非捕获是多余的,c)去掉正斜杠港口。总之看regex101.com/r/wdE30O/5【参考方案2】:
如果您使用的是Python
,您可以编写自己的解析器:
from parsimonious.grammar import Grammar
from parsimonious.nodes import NodeVisitor
data = """git@github.com:james/example
git@github.com:007/example
git@github.com:22/james/example
git@github.com:22/007/example"""
class GitVisitor(NodeVisitor):
grammar = Grammar(
r"""
expr = user at domain colon rest
user = word+
domain = ~"[^:]+"
rest = (port path) / path
path = word slash word
port = digits slash
slash = "/"
colon = ":"
at = "@"
digits = ~"\d+"
word = ~"\w+"
""")
def generic_visit(self, node, visited_children):
return visited_children or node
def visit_user(self, node, visited_children):
return "user": node.text
def visit_domain(self, node, visited_children):
return "domain": node.text
def visit_rest(self, node, visited_children):
child = visited_children[0]
if isinstance(child, list):
# first branch, port and path
return "port": child[0], "path": child[1]
else:
return "path": child
def visit_path(self, node, visited_children):
return node.text
def visit_port(self, node, visited_children):
digits, _ = visited_children
return digits.text
def visit_expr(self, node, visited_children):
out =
_ = [out.update(child) for child in visited_children if isinstance(child, dict)]
return out
gv = GitVisitor()
for line in data.split("\n"):
result = gv.parse(line)
print(result)
这会产生
'user': 'git', 'domain': 'github.com', 'path': 'james/example'
'user': 'git', 'domain': 'github.com', 'path': '007/example'
'user': 'git', 'domain': 'github.com', 'port': '22', 'path': 'james/example'
'user': 'git', 'domain': 'github.com', 'port': '22', 'path': '007/example'
解析器允许一些歧义,你显然在这里。
【讨论】:
你知道,我在两个多月前开始参加正则表达式标签以提高我的技能,我觉得我取得了很好的进步;不确定我是否是专家,但至少正则表达式不再显得过于神秘(我大部分归功于使用正则表达式可视化工具)。我从来没有想过我会进入解析器,但你的帖子是如此冷漠“嗯,试试这个解析器”,这可能是我的下一次冒险,哈哈 @MonkeyZeus:很高兴这里有另一个旅行者。一个很好的起点是tomassetti.me/guide-parsing-algorithms-terminology 用于一般概述,github.com/erikrose/parsimonious 用于Python
中的 PEG 解析器。它确实拓宽了可能性。
@MonkeyZeus:无耻的自我宣传:你可以很好地将正则表达式和解析器结合起来,两全其美,见***.com/a/57749422/1231450以上是关于正则表达式匹配 SSH url 部分的主要内容,如果未能解决你的问题,请参考以下文章
无法使用 Java 正则表达式匹配字符串的最后部分 [重复]
使用正则表达式重新字符串匹配提取 URL 链接 - Python