如何在Elixir中操作正则表达式替换字符串

3

我发现自己想在Elixir中这样做:

re_sentence_frag = %r/(\w([^\.]|\.(?!\s|$))*)(?=\.(\s|$))/
Regex.replace(re_sentence_frag, " oh.  a DOG. woOf. ", String.capitalize("\\1"))

当然,那没有任何影响。(它仅仅大写了一次字符串“\1”)。我真正想做的是对replace函数匹配到的每一个字符串应用String.capitalize/1。但是第三个参数不能传递一个函数引用,因此传递&(String.capitalize("\\1"))也不起作用。
这似乎是如此基础,以至于我很惊讶它不可能实现。是否有其他方法可以表达这种操作?看起来底层的Erlang库不会立即支持将函数引用作为第三个参数传递,因此在Elixir中修复这个问题可能不完全简单。
你会如何编程操作每个匹配字符串?

"\\1" 是供正则表达式引擎使用的,而不是 String 类。 - user557597
我会查看函数引用是否为参数选项。该函数接收匹配结果并返回替换字符串。如果无法实现此功能,则必须在正则表达式查找循环中重构新字符串。 - user557597
你最好使用 scan 函数并使用结果中的信息手动替换它们。为了代码重用的目的,你可以创建一个接受函数作为参数的包装器函数。 - nhahtdh
你说得对。我们无法将函数传递到Erlang端,因此支持此功能并不容易。:( 对于这种情况,拆分似乎是最好的方法。 - José Valim
如果分割不支持捕获的分隔符,您可以使用 (?=\w(?:[^\.]|\.(?!\s|$))*)(?=\.(?:\s|$)) 进行分割,然后检查每个元素是否与 \A(\w(?:[^\.]|\.(?!\s|$))*)(?=\.(?:\s|$))(.*)\z 匹配。 如果匹配,则将组1大写并附加,组2是要附加的其余部分。 如果没有匹配,则只需附加该元素。 所有分割和匹配函数都应为单行修饰符 //s 或在所有正则表达式开头放置 (?s) 修饰符组。 - user557597
显示剩余2条评论
1个回答

2

这里是一个基于 split 的解决方案:

" oh.  a DOG. woOf. pi is 3.14159. try version 7.a." |>
String.split(%r/(^|\.)(\s+|$)/)                      |>
Enum.map_join(&String.capitalize/1)

我猜这种方法并不比我最初的尝试更笨拙。正则表达式要简单得多,因为它只需要找到句子之间的部分。


我在你最初发布的问题下留了一些关于split的评论。不知道是否有帮助。 - user557597

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接