我有一个巨大的三元组列表,如下所示:
?s ex:url ?url
其中?url
可以是:
www.ex.com/data/1.html
www.ex.com/data/2.html
www.google.com/search
...
使用SPARQL查询,是否可以以某种方式过滤查询并获得不同的域列表?在示例中,www.ex.com
和www.google.com
。
类似这样的东西:
SELECT distinct ?url
WHERE { ?s ex:url ?url }
但是处理每个url绑定。当然,我可以得到所有这些,并在程序中逐一处理每个url,但我认为sparql查询会更节省内存。我正在使用Stardog,以防它有一些自定义功能。
您可以使用不需要正则表达式的字符串操作来完成类似的操作。例如,您可以采用URL的字符串形式的"之后的部分//"并且在"0"之前/":
select ?url ?hostname {
values ?url { <http://example.org/index.html> }
bind(strbefore(strafter(str(?url),"//"),"/") as ?hostname)
}
---------------------------------------------------
| url | hostname |
===================================================
| <http://example.org/index.html> | "example.org" |
---------------------------------------------------
这不使用正则表达式,并且可能比使用regex函数的解决方案更快。
然而,这可能会让您获得更多的主机名,例如,如果URL类似于http://username:password@example.org/8080,您可以在其中获得用户名:password@example.org:8080,这不仅仅是主机名。
为了更仔细地做到这一点,您需要选择一个URI/URL等规范,如RFC 3986,并查看语法组件部分。该语法的一些相关产物是:
URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ] hier-part = "//" authority path-abempty / path-absolute / path-rootless / path-empty
权限组件前面有一个双斜线("//"(以下一个斜线("/"(、问号("?"(或数字结尾符号("#"(字符或通过URI的末尾。
authority = [ userinfo "@" ] host [ ":" port ]
我不会处理所有这些(也许使用正则表达式来处理复杂的情况会更有意义(,但最简单的方法可能是从SPARQL结果中获取URI,然后使用实际的URI解析库来获取主机名。这是最可靠的解决方案,因为URI可能非常复杂。
使用REPLACE与REGEX:
BIND(REPLACE(STR(?url), "^(.*?)/.*", "$1") AS ?domain)
Yasgui 中的示例
编辑:正如@JoshuaTailor在评论中指出的那样,如果没有方案,STRBEFORE会更好吗?网址:
BIND(STRBEFORE(?url, "/") AS ?domain)
如果你需要担心URL方案(这会放弃该方案(:
BIND(REPLACE(STR(?url), "^(https?://)?(.*?)/.*", "$2") AS ?domain)
当然,以上仅适用于基本的http(s(URL,如果需要处理任意URL,则正则表达式会变得更加复杂。
这里有一个可以处理任何或丢失的方案、端口号、身份验证信息和丢失的尾部斜杠:
BIND(REPLACE(?url, "^(?:.*?://)?(?:.*?@)?([^:]+?)(:\d+)?((/.*)|$)", "$1") AS ?domain)
请注意,使用正则表达式的查询可能非常慢。