clojure - 使用Clojure解析数据,间隔问题

标签 clojure

我正在用clojure编写一个小解析器以用于学习目的。
基本上是一个TSV文件解析器,需要放在数据库中,但是我增加了一个麻烦。
复杂的是,在同一文件中有更多的时间间隔。
该文件如下所示:

###andreadipersio 2010-03-19 16:10:00###                                                                                
USER     COMM               PID  PPID  %CPU %MEM      TIME  
root     launchd              1     0   0.0  0.0   2:46.97  
root     DirectoryService    11     1   0.0  0.2   0:34.59  
root     notifyd             12     1   0.0  0.0   0:20.83  
root     diskarbitrationd    13     1   0.0  0.0   0:02.84`
....

###andreadipersio 2010-03-19 16:20:00###                                                                                
USER     COMM               PID  PPID  %CPU %MEM      TIME  
root     launchd              1     0   0.0  0.0   2:46.97  
root     DirectoryService    11     1   0.0  0.2   0:34.59  
root     notifyd             12     1   0.0  0.0   0:20.83  
root     diskarbitrationd    13     1   0.0  0.0   0:02.84

我最终得到了这段代码:
(defn is-header? 
  "Return true  if a line is header"
  [line]
  (> (count (re-find #"^\#{3}" line)) 0))

(defn extract-fields
  "Return regex matches"
  [line pattern]
  (rest (re-find pattern line)))

(defn process-lines
  [lines]
  (map process-line lines))

(defn process-line
  [line]
  (if (is-header? line)
    (extract-fields line header-pattern))
  (extract-fields line data-pattern))

我的想法是在“生产线”间隔中需要与数据合并,所以我有这样的事情:
('andreadipersio', '2010-03-19', '16:10:00', 'root', 'launchd', 1, 0, 0.0, 0.0, '2:46.97')

对于每一行,直到下一个间隔,但我无法弄清楚如何做到这一点。

我尝试过这样的事情:
(def process-line
  [line]
  (if is-header? line)
    (def header-data (extract-fields line header-pattern)))
  (cons header-data (extract-fields line data-pattern)))

但是,这并不异常(exception)。

有什么提示吗?

谢谢!

最佳答案

您正在执行(> (count (re-find #"^\#{3}" line)) 0),但是您可以执行(re-find #"^\#{3}" line)并将结果用作 bool 值。如果匹配失败,re-find返回nil

如果要遍历集合中的项目,并且想跳过某些项目或将原始项目中的两个或多个项目合并为一个项目,那么有99%的时间需要reduce。这通常最终非常简单。

;; These two libs are called "io" and "string" in bleeding-edge clojure-contrib
;; and some of the function names are different.
(require '(clojure.contrib [str-utils :as s]
                           [duck-streams :as io])) ; SO's syntax-highlighter still sucks

(defn clean [line]
  (s/re-gsub #"^###|###\s*$" "" line))

(defn interval? [line]
  (re-find #"^#{3}" line))

(defn skip? [line]
  (or (empty? line)
      (re-find #"^USER" line)))

(defn parse-line [line]
  (s/re-split #"\s+" (clean line)))

(defn parse [file]
  (first
   (reduce
    (fn [[data interval] line]
      (cond
       (interval? line) [data (parse-line line)]
       (skip? line)     [data interval]
       :else            [(conj data (concat interval (parse-line line))) interval]))
    [[] nil]
    (io/read-lines file))))

关于clojure - 使用Clojure解析数据,间隔问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2538326/

相关文章:

clojure - 使用嵌套参数执行 lein 别名会引发错误

javascript - 从 Javascript 调用 ClojureScript

clojure - 如何解构即时并从 java 时间库中提取年、月等

clojure - Clojure 的标准?

clojure - 在 Clojure deftype 中重写 equals、hashCode 和 toString

clojure - Compojure 应用程序默认不发送 CSRF

clojure - 在莱宁根哪里可以找到依赖项的有效版本号

clojure - 如何设置 clojureScript 项目以使用规范并在运行时测试 clojure.core 函数?

clojure - loop-recur 怎么可能抛出 StackOverflowError?

java - 将 Java 对象方法调用结果转换为 Clojure 映射