clojure regex命名组

vybvopom  于 2023-10-22  发布在  其他
关注(0)|答案(3)|浏览(106)

我在clojure中有一个re-find的问题。实际上我在做

(re-find #"-(?<foo>\d+)-(?<bar>\d+)-(?<toto>\d+)-\w{1,4}$" 
"http://www.bar.com/f-a-c-a-a3-spok-ser-2-phse-2-1-6-ti-105-cv-9-31289-824-gu" )

我的结果很好:

["-9-31289-824-gt" "9" "31289" "824"]

但我更喜欢这样的哈希:

{:foo "9" :bar "31289" :toto "824"}

我知道java.util.regex.Matcher/group正在做类似的事情,但我不能正确地使用它。谢谢你的帮助

wxclj1h5

wxclj1h51#

Clojure构建的java regex库(Java 1.6)不支持regex命名的捕获组。
但是,您可以使用Clojure的zipmap函数将合并名称键和re-find捕获的组组合到一个map中。不匹配的组将获得名称键的nil值。

(zipmap [:foo :bar :toto]
        (rest (re-find #"-(\d+)-(\d+)-(\d+)-\w{1,4}$" 
                        "http://www.bar.com/f-a-c-a-a3-spok-ser-2-phse-2-1-6-ti-105-cv-9-31289-824-gu")))

=> {:foo "9" :bar "31289" :toto "824"}
mwg9r5ms

mwg9r5ms2#

JDK直到JDK 7才支持命名捕获组。
Here's announcement on oracle blog
报价:
这个方便的特性在Java RegEx中已经被忽略了很多年,现在它终于在JDK 7 b50中得到了体现。
由于clojure支持JDK >= 6,如果你正在寻找一些原生的东西(clojure在幕后使用java regex Patterns和Matchers),那你就不走运了。
您可以始终使用外部库,如named-re。这一个给你正是你需要的。
调用

(require 'named-re.core)
(re-find #"-(?<foo>\d+)-(?<bar>\d+)-(?<toto>\d+)-\w{1,4}$" 
     "http://www.bar.com/f-a-c-a-a3-spok-ser-2-phse-2-1-6-ti-105-cv-9-31289-824-gu" )

将返回

{:toto "824", :bar "31289", :foo "9", :0 "-9-31289-824-gu"}
jhdbpxl9

jhdbpxl93#

这在Java中是一个长期的限制。没有用于获取命名捕获组列表的API。看看这个question
当使用不支持此功能的Java版本时,您所能做的就是使用外部库。
如果不需要Map,可以使用Clojure文档中描述的解决方案。在您的情况下,解决方案可以类似于这样:

(let [matcher (re-matcher #"-(?<foo>\d+)-(?<bar>\d+)-(?<toto>\d+)-\w{1,4}$"
                          "http://www.bar.com/f-a-c-a-a3-spok-ser-2-phse-2-1-6-ti-105-cv-9-31289-824-gu")]
  (re-find matcher)
  (re-groups matcher)
  (.group matcher "foo"))

尽管这个解决方案并不完美(匹配器是一个可变的Java对象),但它是有效的。
正如我链接的另一个答案中所写的那样,自2023年3月21日发布的Java 20以来,有一个解决方案。

(let [matcher (re-matcher #"-(?<foo>\d+)-(?<bar>\d+)-(?<toto>\d+)-\w{1,4}$"
                          "http://www.bar.com/f-a-c-a-a3-spok-ser-2-phse-2-1-6-ti-105-cv-9-31289-824-gu")]
  (re-find matcher)
  (re-groups matcher)
  (.namedGroups matcher))

这是你想要的
我不得不手动安装JDK 20。JRE不适合我。但是在安装了JDK 20之后,Clojure接受了它,它对我很有效。不需要配置。
使用ClojureScript显然这根本不起作用。

相关问题