如何编写通用SPARQL查询提取URI最后斜杠后的末尾部分
问题
我有一列来自不同域名的URI,示例如下:
http://comicmeta.org/cbo/category http://purl.org/dc/terms/hasVersion http://schema.org/contributor
需要提取每个URI的最后一部分,即每个URI中最后一个斜杠/之后的字符串。针对上述URI列表,预期提取结果为:
category hasVersion contributor
需要编写通用SPARQL查询,实现从任意给定URI中提取该末尾部分的需求。
原有尝试的查询语句如下:
SELECT distinct ?s ?x WHERE { ?s ?p ?o . BIND (STRBEFORE(STRAFTER(STR(?s),"/"), " ") as ?x) . # 意图提取斜杠'/'之后、空格' '标识的字符串末尾之前的内容 }
执行该语句后仅返回空字符串"",无法得到预期结果,需要修改语句实现需求。
错误原因
原有写法有两个核心问题:
STRAFTER(STR(?s),"/")只会匹配字符串中第一个/之后的所有内容,不会定位到最后一个斜杠,比如对第一个示例URI,该函数返回值是/comicmeta.org/cbo/category,并非目标片段- 合法URI中不存在空格字符,
STRBEFORE(..., " ")以空格为分隔符匹配内容,自然只能返回空值。
解决方案
正则写法(最简洁,全SPARQL 1.1引擎兼容)
直接用REPLACE配合正则,匹配从字符串开头到最后一个斜杠的所有内容,将其替换为空,剩余部分就是需要的末尾片段,不需要提前感知URI的结构、斜杠数量:
SELECT DISTINCT ?s ?x WHERE { ?s ?p ?o . BIND(REPLACE(STR(?s), "^.*/([^/]*)$", "$1") AS ?x) }
正则表达式^.*/([^/]*)$的含义:
^.*/:匹配从字符串开头到最后一个出现的/的所有字符([^/]*)$:捕获最后一个/之后到字符串结尾的所有非斜杠字符$1代表取第一个捕获组的内容,也就是目标片段
无正则写法(性能更优,适配超大三元组库场景)
如果数据集规模很大,正则匹配性能不足,可以用字符串反转+位置计算的方式定位最后一个斜杠,逻辑同样通用:
SELECT DISTINCT ?s ?x WHERE { ?s ?p ?o . BIND(STR(?s) AS ?sStr) # 反转字符串后取第一个斜杠前的内容长度,即可算出原字符串最后一个斜杠的位置 BIND(STRLEN(STRBEFORE(REVERSE(?sStr), "/")) AS ?tailLen) BIND(SUBSTR(?sStr, STRLEN(?sStr) - ?tailLen + 1) AS ?x) }
两种写法对你给出的示例URI,都会返回预期的category、hasVersion、contributor结果,对任意结构的合法URI都通用。
内容的提问来源于stack exchange,提问作者AnonymousMe
相关产品推荐
相关产品推荐

