Clojure中修剪不可打印字符的通用方法

6
我遇到了一个错误,我无法将两个看起来“相同”的字符串匹配在一起。例如,以下两个字符串无法匹配: "sample" 和 "​sample"。
为了复制这个问题,可以在Clojure中运行以下命令。
(= "sample" "​sample") ; returns false

在经过一个小时沮丧的调试后,我发现第二个字符串开头有一个零宽度空格!通过一个退格键从这个特定示例中删除它是微不足道的。然而,我有一个字符串数据库需要匹配,似乎有多个字符串面临这个问题。我的问题是:有没有一种通用的方法可以在Clojure中修剪零宽度空格? 我尝试了一些方法:
(count (clojure.string/trim "​abc")) ; returns 4

(count (clojure.string/replace "​abc" #"\s" "")) ; returns 4

这个线程提供了一个使用正则表达式的解决方案,可以在此示例中起作用,即删除JavaScript字符串中的零宽度空格字符。

(count (clojure.string/replace "​abc" #"[\u200B-\u200D\uFEFF]" "")) ; returns 3

然而,正如帖子本身所述,还有许多其他可能是不可见的ASCII字符。因此,我仍然感兴趣是否有一种更一般的方法,不依赖于列出所有可能的不可见Unicode符号。


1
我不知道Clojure中是否有内置函数可以实现你想要的功能。我刚刚阅读了https://en.wikipedia.org/wiki/Zero-width_space,以更熟悉0宽度字符。不幸的是,为了解决你的问题,我认为你应该手动维护一个要修剪的字符列表。 - Rozar Fabien
2个回答

4

我相信你所提到的是所谓的不可打印字符。根据Java中这个答案,你可以将#"\p{C}"正则表达式作为模式传递给replace

(defn remove-non-printable-characters [x]
  (clojure.string/replace x #"\p{C}" ""))

但是这样做会删除换行符,例如\n。因此,为了保留这些字符,我们需要一个更复杂的正则表达式:

(defn remove-non-printable-characters [x]
  (clojure.string/replace x #"[\p{C}&&^(\S)]" ""))

这个功能将移除不可打印的字符。让我们来测试一下:
(= "sample" "​sample")
;; => false

(= (remove-non-printable-characters "sample")
   (remove-non-printable-characters "​sample"))
;; => true

(remove-non-printable-characters "sam\nple")
;; => "sam\nple"

这里讨论了\p{C}模式,具体信息请查看此处


1
非常好,谢谢 :) 还值得注意的是,此方法会删除控制字符,包括 '\n',但不影响普通空格 - Desmond Cheong
啊,谢谢指出!我没有注意到。我会看看能否在答案中对此进行改进。 - Rulle

1

@Rulle提供的正则表达式解决方案非常好。tupelo.chars 命名空间还包括一些可能有用的字符类和谓词函数,它们可在Clojure和ClojureScript中使用,并提供了适用于浏览器的^nbsp;。特别是,请查看visible?谓词。

tupelo.string命名空间还提供了许多辅助和便捷字符串处理函数。

(ns tst.demo.core
  (:use tupelo.core tupelo.test)
  (:require
    [tupelo.chars :as chars]
    [tupelo.string :as str] ))

(def sss
"Some multi-line
string." )

(dotest
  (println "result:")
  (println
    (str/join
      (filterv
        #(or (chars/visible? %) 
             (chars/whitespace? %))
        sss))))

带有结果
result:
Some multi-line
string.

使用方法如下,让你的project.clj看起来像这样:
  :dependencies [
                 [org.clojure/clojure "1.10.2-alpha1"]
                 [prismatic/schema "1.1.12"]
                 [tupelo "20.07.01"]
                 ]

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