【问题标题】:Title Case Conversion in SPARQL Query with REGEX使用 REGEX 的 SPARQL 查询中的标题大小写转换
【发布时间】:2021-11-24 23:13:31
【问题描述】:

我离我的问题的解决方案只有一英寸的距离。我正在尝试对通过 SPARQL 检索到的字符串进行标题大小写转换。我将 REPLACE 函数与 LCASE 和 REGEX 结合使用:

BIND (replace(lcase(?label), "(\\b[a-z](?!\\s))", ucase("$1") ) as ?title_case)

lcase(?label):字符串中的所有字符变为小写

(\\b[a-z](?!\\s)):匹配字符串中每个单词的首字母

ucase($1): 是对匹配的第一个字母的反向引用,将其转换为大写后作为替换。

预期结果:animal husbandry methods 变为 Animal Husbandry Methods

由于我无法理解的原因,该解决方案几乎可以正常工作,但并不完全正确;查看here 工作中的示例。

当您运行查询时,您不会注意到 ?title_case 有任何不同,但如果您将 ucase("$1") 编辑为 ucase("aaa"),您会看到它神奇地正确替换了每个单词的第一个字母:

结果:animal husbandry methods 变为 AAAnimal AAAusbandry AAAethods

在我看来,UCASE 函数对反向引用 $1 没有任何影响

谁能向我解释为什么会这样,如何纠正这种行为?

【问题讨论】:

  • 在转向使用 ucase($1) 之前,我尝试了使用 REGEX 附带的\U$1\E 的解决方案,其中 \U 开始大写,而 \E 结束它。我还没有找到正确的字符转义形式,这使得 SPARQL 有效并且结果符合我的预期!
  • 我不太确定您在哪里找到了 \U\E 命令。我无法在 SPARQL 规范中找到它们,也无法在从中获取 replace 的 XPath 中找到它们。
  • 我试图使用我发现解释的 \U \E 方法here 但出于挫败感再次尝试了许多尝试。
  • 啊,是的,这似乎只适用于 vim。但是,在所有正则表达式方言中都有肯定会很好。

标签: regex sparql rdf jena linked-data


【解决方案1】:

SPARQL 中的函数调用遵循大多数编程语言的传统约定,即首先计算内部函数,然后将它们的返回值作为参数提供给外部函数。 replace 这里有 3 个字符串,输入字符串、模式和替换。 ucase 独立于结果的使用方式进行解释,它只是将其参数转换为大写,令人惊讶的是,$1 的大写是$1

在其他语言中,您通常会使用接受函数/表达式而不是字符串作为替换的函数的某些重载,以便您可以从内部调用任何内容。这在 SPARQL 中是不可能的,replace 函数所能做的就是插入未修改的捕获。

恐怕您想做的事情仅在 SPARQL 中无法完全实现。您的选择是:

  • 使用 SPARQL 扩展,其中包含一个功能,如果端点支持的话。
  • 如果您的查询是较大管道的一部分,请以其他方式转换结果,例如使用 XSLT。
  • 由于你只关心[a-z],你可以简单的展开所有的字母,一个一个替换:replace(replace(lcase(?label), "(\\ba(?!\\s))", "A" ), "(\\bb(?!\\s))", "B" )等等。不是一个非常优雅或高性能的解决方案,但它可以完成工作。
  • 更短的选项是使用^(.*?)(\b[a-z](?!\s))(.*)$ 之类的模式将字符串拆分为 3 部分,您可以分别将其提取为替换为$1$2$3。将第一部分与第二部分的大写连接起来,然后对最后一部分重复整个过程。您将不得不再次重复这些模式,但这次是相同的模式,因此有优化的潜力。一个缺点是你必须在某个地方结束这个“递归”,所以你只能替换固定数量的单词。

【讨论】:

  • 非常感谢重播并清除了我关于为什么会出现这种行为的询问。事实上,我的工作印象是,使用 REGEX 的替换是以某种方式在 SPARQL 之外使用与 REGEX 相同的执行逻辑来处理的。我确实尝试使用 SPARQL 的 GraphDB 实现,它甚至有一个 spif:titleCase() 函数,但我也有一个意想不到的行为。我发布了question,希望 Ontotext 的人能解释一下。
  • 一开始我以为我理解了你的推理,但是在第二次阅读时我仍然不明白为什么如果 $1 持有第一个字母,那么 ucase() 没有大写它,即使它是第一个执行的函数。你说ucase()确实把$1大写了,但是replace()中没有用到结果?我很困惑,因为 ucase('aaa') 确实按预期工作,让我明白 replace 确实使用它进行替换。再次感谢您的宝贵时间。
  • 我确实尝试使用 SPARQL 的 GraphDB 实现,它甚至有一个 spif:titleCase() 函数,但我也有一个意想不到的行为。我发布了question,希望 Ontotext 的人能解释一下。
  • @Menelao "$1" 只是一个由两个字符组成的字符串。 ucase 将它们都转换为大写,结果,碰巧仍然是"$1",被传递给replace,它不知道在此之前它经历了什么。您链接的问题也有同样的困惑。从 SPARQL 的角度来看,"$1" 在语法上没有什么特别之处,它只是一个受其他字符串相同规则支配的字符串。
  • 我真的不是要浪费你的时间,但是当你访问到 SPARQL 端点的链接并运行查询时,如果你说 $1 只是一个字符串,那么我不应该收到用 $1 作为首字母替换的标签(例如 $1nimal $1usbandry $1ethods)?为什么我看到第一个字母正确放置?为什么如果我输入 ucase("$1.") 我会看到第一个字母与 DOT 与标签字符串的其余部分分开?换句话说,为什么 ucase() 没有效果?
猜你喜欢
  • 1970-01-01
  • 2011-02-15
  • 2020-07-25
  • 2014-11-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多