String Clojure:第一个空格分隔字符的印章

String Clojure:第一个空格分隔字符的印章,string,parsing,filter,clojure,String,Parsing,Filter,Clojure,我想分析和筛选一个如下所示的文件: @@1 Row one. @@2 Row two. 我已经能够使用以下代码对行进行筛选: (defn parse-text-cms [sel-row] (let [f_data (st/split #"@@" (slurp "cms/tb_cms.txt"))] ;(prn (map #(take 1 %) f_data)))) (filter #(= (first (take 1 %)) sel-row) f_data))) 但是,

我想分析和筛选一个如下所示的文件:

@@1 Row one. 
@@2 Row two.
我已经能够使用以下代码对行进行筛选:

(defn parse-text-cms [sel-row]
  (let [f_data  (st/split  #"@@" (slurp "cms/tb_cms.txt"))] 
  ;(prn (map #(take 1 %) f_data))))
  (filter  #(= (first (take 1 %)) sel-row) f_data)))
但是,该代码给出(如果sel row=1):

我想切掉1和后面的空格,以便:

Row one.

我认为有一些序列魔法可以做到这一点。我就是想不出一个优雅的解决方案。

我会用以下方式定义函数:

(defn parse-text-cms [sel-row]
  (with-open [input (clojure.java.io/reader "cms/tb_cms.txt")]
    (first
     (for [[_ number line] (map (partial re-find #"@@(\d)+\s+(.*)")
                                (line-seq input))
           :when (= number (str sel-row))]
       line))))
line seq
reader
的组合为我提供了输入文件中的一系列行<代码>打开确保文件在我完成时正确关闭。我对查找
@
后跟数字和一些空格的每一行应用一个正则表达式

重新查找
返回包含三项的向量:

  • 整条线都匹配
  • 编号(正则表达式中的第一个组)
  • 行的其余部分(正则表达式中的第二组)
我在
for
语句中使用解构将它们绑定到
number
line
(我对匹配的整行不感兴趣,所以忽略它)。我使用
:when
过滤所选
sel行
,并仅产生(剩余的)

因为我只希望文件中有一个匹配项,所以我只返回由
构建的序列中的第一项。由于
for
map
line seq
的惰性,这也会在找到项目后停止读取文件


如果您对行进行大量查找,我建议您将整个文件加载到内存中,而不是每次都读取它。

前面给出的答案使用
line seq
和正则表达式组的解构对于给定的用例很有效

在一般情况下,您只需要对字符串进行操作,clojure.core包含
subs
函数

subs
是使用java互操作和java字符串类的substring方法实现的


user=> (subs "abcdef" 1)
"bcdef"
user=> (subs "abcdef" 2 4)
"cd"

另一个解决方案是使用一个函数解析器库,比如dj-peg(我写的)

然后你可以写下:

 (require '[dj-peg :as p])
 (let [line "@@1 the remaining line\n"
       initial (p/token #"@@\d+\s+)]
       (second (p/parse initial line)))
函数parse使用p/token返回的解析器来解析第行中的文本。它将返回一个向量,第一个值作为解析的结果,第二个值是剩余的输入。因此,如果我们叫第二个,我们就得到了剩余的线路。运行此命令将返回

 "the remaining line\n"

我建议你去图书馆看看。它是以伪读写编程风格编写的,因此源代码读起来相当流畅。阅读源代码后,您应该能够理解解析模型。

应该使用open表单在周围的
中创建
读取器
。谢谢。我是clojure的新手,您能提供更多关于内存加载的信息吗?也许是一些医生?
 "the remaining line\n"