Clojure中的CSV解析器需要避免使用引号

时间:2015-12-26 20:45:29

标签: regex csv clojure

更新:传递:

#",(?=([^\"]*\"[^\"]*\")*[^\"]*$)"

clojure.string/split解析CSV。

更新:我需要一个匹配所有非引号的逗号的正则表达式,其格式可以由clojure.string/split使用。

我在Clojure中编写了一个CSV解析函数:

(defn parse-csv [data schema]
  (let [split-data (clojure.string/split data #",")]
    (loop [rm-data split-data
           rm-keys (:keys schema)
           rm-trans (:trans schema)
           final {}]
      (if (empty? rm-keys)
           final
          (recur (rest rm-data)
                 (rest rm-keys)
                 (rest rm-trans)
                 (into final
                   {(first rm-keys)
                   ((first rm-trans) (first rm-data))}))))))

schema只是一个哈希映射,由关键字列表和函数列表组成(应用于各自的值)。这用于定义输出哈希映射的外观。 这是一个例子:

(def schema {:keys [:foo :bar :baz] :trans [identity read-string identity]})
(parse-csv "Hello,42,world" schema) ;; returns {:foo "Hello", :bar 42, :baz "world"}

但是,如果我们这样做:

(def schema {:keys [:foo :bar :baz] :trans [identity identity identity]})
(parse-csv "Hello,\"Newell, Gabe\",world" schema) ;; returns {:foo "Hello" :bar "\"Newell" :baz "Gabe\""}

事情搞砸了,“世界”这个词被忽略了。结果应该看起来像:

{:foo "Hello" :bar "\"Newell, Gabe\"" :baz "world"}

以上数据在文件中实际上看起来像Hello,"Newell, Gabe",world,因此我们需要避免在split中遇到逗号时触发"Newell, Gabe"函数。

我们需要一个将某个字符串拆分的函数,除非某个字符在引号中。

1 个答案:

答案 0 :(得分:0)

要允许字段内的分隔符(此处为,),需要引用这些字段。

您在此处使用\"执行的操作转义引号(unix样式,引号也可以使用其他引号进行转义)。

因此,允许字段内的,

"Hello,"Newell, Gabe",world"

当然,那些外部引号不应该是csv的一部分。

编辑问题后

Udate

  

以上数据在文件中实际上看起来像Hello,“Newell,   Gabe“,世界,所以我们需要避免触发分裂功能   在“Newell,Gabe”中出现了逗号。

Hello,"Newell, Gabe",world

这是完全有效的csv,但如果使用,上的纯分割功能处理此问题,则会遇到麻烦。

一种选择可能是使用其他分隔符,例如|;

更新2

  

所以我需要一个新功能,将CSV字符串拆分为字段,除非   逗号是引号(我无法更改数据集)。我怎么去   关于实现这个?

对于每一行,你需要扫描每个字符,在伪代码中有点像这样(我不知道Clojure,所以我不能提供一些代码,但我用大csv文件工作了很多):

bool InsideQuotes = false;
loop through chars
  if `,` and InsideQuotes == false -> new field
  if `"` -> InsideQuotes = !InsideQuotes

这种方式引用字段内的引号可以使用另一个引号进行转义。例如:

Hello,"17"" monitor, Samsung",world

<强>更新

对于csv上的某些Regex,请参阅thisthis