如何将Clojure文本文件匹配行转为保留引号的列表而非字符串?
解决Clojure文本解析中字符串引号的问题
首先要明确:你用read-string解析后,"Cigarros"并没有真的失去引号——它仍然是字符串类型,只是Clojure的println等输出方式默认不显示引号,而REPL直接输出时会显示。如果你的其他函数因此出错,大概率是函数逻辑对数据类型的判断有误,而非解析后的结构问题。
修正你的locate函数
原函数存在两个小问题:
filter返回的空序列在if判断中会被视为逻辑真,导致无匹配时仍执行first(结果为nil,虽然最终结果正确,但逻辑冗余)- 逐行解析不如直接读取整个文件的Clojure数据结构可靠
改进后的函数直接读取整个文件并解析为嵌套列表,再过滤匹配项:
(defn locate [token filename] (with-open [rdr (clojure.java.io/reader filename)] (let [full-data (read-string (slurp rdr)) matched-item (first (filter #(.contains (str %) token) full-data))] matched-item)))
调用这个函数后,返回的就是标准的Clojure列表,比如匹配"Cigarros"时会得到:
(A12 54 "Cigarros" 10)
此时(seq? matched-item)返回true,且第三个元素是字符串类型的"Cigarros",完全符合你的需求。
如果确实需要带引号的字符串元素
若你的其他函数要求字符串元素是包含引号的文本(比如存储为"\"Cigarros\""),可以在解析后对列表元素做转换:
(defn wrap-strings-with-quotes [lst] (map #(if (string? %) (str "\"" % "\"") %) lst)) ;; 使用示例 (let [matched (locate "Cigarros" "backend.txt")] (wrap-strings-with-quotes matched))
转换后的结果为:
(A12 54 "\"Cigarros\"" 10)
此时第三个元素是包含引号的字符串,输出时会显示引号。
验证数据类型的小技巧
你可以用type函数确认解析后的元素类型:
(let [matched (locate "Cigarros" "backend.txt")] (type (nth matched 2))) ;; => java.lang.String
这说明解析后的元素确实是字符串,只是输出显示方式不同而已。
内容的提问来源于stack exchange,提问作者user19921500
相关产品推荐
相关产品推荐

