匹配 SSH url 部分的正则表达式
Regex to match SSH url parts
给定以下 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 port}{path (user/repo)}
如您在示例中所见,其中一个用户名是数字而不是端口。我不知道如何解决这个问题。端口也不总是在 URL 中。
我当前的正则表达式是:
^(?P<user>[^@]+)@(?P<host>[^:\s]+)?:(?:(?P<port>\d{1,5})\/)?(?P<path>[^\].*)$
不确定还能尝试什么。
惰性量词来拯救!
这似乎运行良好并满足可选端口:
^
(?P<user>.*?)@
(?P<host>.*?):
(?:(?P<port>.*?)/)?
(?P<path>.*?/.*?)
$
换行符不是正则表达式的一部分,因为启用了 /x
修饰符。如果您不使用 /x
.
,请删除所有换行符
https://regex101.com/r/wdE30O/5
谢谢@Jan for the 。
如果您使用 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'}
解析器允许您在此处显然存在的一些歧义。
给定以下 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 port}{path (user/repo)}
如您在示例中所见,其中一个用户名是数字而不是端口。我不知道如何解决这个问题。端口也不总是在 URL 中。
我当前的正则表达式是:
^(?P<user>[^@]+)@(?P<host>[^:\s]+)?:(?:(?P<port>\d{1,5})\/)?(?P<path>[^\].*)$
不确定还能尝试什么。
惰性量词来拯救!
这似乎运行良好并满足可选端口:
^
(?P<user>.*?)@
(?P<host>.*?):
(?:(?P<port>.*?)/)?
(?P<path>.*?/.*?)
$
换行符不是正则表达式的一部分,因为启用了 /x
修饰符。如果您不使用 /x
.
https://regex101.com/r/wdE30O/5
谢谢@Jan for the
如果您使用 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'}
解析器允许您在此处显然存在的一些歧义。