【问题标题】:Can python's csv reader leave the quotes in?python的csv阅读器可以留下引号吗?
【发布时间】:2013-02-24 01:10:09
【问题描述】:

我想使用 python CSV 阅读器,但我想保留引号。这就是我想要的:

>>> s = '"simple|split"|test'
>>> reader = csv.reader([s], delimiter='|', skipinitialspace=True)
>>> reader.next()
['"simple|split"', 'test']

但我实际上得到了:

['simple|split', 'test']

在我的情况下,我希望引用的字符串仍然被引用。

我知道 CSV 阅读器正在按预期工作,我的用例是对它的滥用,但有什么方法可以让我按照自己的意愿来使用它吗?还是我必须编写自己的字符串解析器?

【问题讨论】:

  • 您必须编写自己的解析器。引号是一种转义数据的方法,否则这些数据不会被视为一列,因此不被视为输出的一部分。
  • 根据数据的复杂程度,您可能会作弊并使用像 filter(None, re.split(r'(".*?")|\|', s)) 这样可怕的东西 - 或查看 pyparsing
  • 您好,我发布了一个答案,实际上我开发了 Martjin 和 Jon 所说的内容。你能说说你为什么不考虑使用正则表达式吗?

标签: python csv quotes


【解决方案1】:

您将不得不编写自己的解析器,因为支持解析和引用的模块部分位于 C 端,尤其是位于 Modules/_csv.c 中的 parse_process_char

    else if (c == dialect->quotechar &&
             dialect->quoting != QUOTE_NONE) {
        if (dialect->doublequote) {
            /* doublequote; " represented by "" */
            self->state = QUOTE_IN_QUOTED_FIELD;
        }
        else {
            /* end of quote part of field */
            self->state = IN_FIELD;
        }
    }
    else {
        /* normal character - save in field */
        if (parse_add_char(self, c) < 0)
            return -1;
    }

“字段的引号部分结束”部分是你的双引号。另一方面,您可能能够杀死 else 条件并重建 python 源代码。然而,说实话,这并不是那么容易维护的。

编辑:对不起,我的意思是在self-&gt;state = IN_FIELD 之前添加最后一个else 的位,因此它会添加引号。

【讨论】:

  • 这是一个非常明确的答案!谢谢。
  • @HamishDowner 实际上,我对使用 PyPy(Python 中的 Python)的模块并对其进行修改以创建可以放入项目中的自定义模块有一个想法。我会玩弄它,看看我能不能让它工作,这样你就不必重新发明任何轮子了。
  • @HamishDowner 是的,我试了一下,但 PyPy 的 csv 模块代码,即使是在 python 中,仍然有很多 pypy 导入分散在各处。不幸的是,这有点太费力了。如果您需要有关如何处理解析器工作的一些想法,可能想看看他们的csv reader code
  • @cwgem 篡改模块的源代码在我看来是一项繁重的工作,而使用正则表达式很容易。
【解决方案2】:

我不明白你是否清楚地了解你想要获得的东西。
你说“我知道(...)我的用例是一种滥用”
但滥用意味着存在使用的可能性。
但是,在您的情况下,没有可能的用途,您“描述”的内容是不可能的,因为传递给 CSV 解析器的内容必须是有效的 CSV 格式,而您的不是。

在 CSV 有效字符串中,大部分字符是信息,而一些字符是解释字符串以提取信息所必需的元信息。
您描述的是您希望字符" 应该完全属于信息类别和元信息类别。就像有人想用左手抓住他/她的左手.....

您的字符串出现此问题,因为它不是来自读取 CSV 文件的字符串。这是一个按原样编写的字符串。
从 CSV 文件的读取中获取这样的字符串是不可能的,因为它不可能像这样写在 CSV 文件中。
如果写入 CSV 文件,则可以写入 '"simple|split"|test'

  • """simple|split"""|test
    doublequote 设置为 True,默认

  • #"simple#|split#"|test
    doublequote = False, escapechar = '#'

如果你想像你描述的那样提取信息,你不必创建解析器,你只需要使用一个已经存在的工具:

import re

reg = re.compile('".*?"|[^|]+')

print reg.findall('yoo|"simple|split"|test|end"pos|hu')

结果

['yoo', '"simple|split"', 'test', 'end"pos', 'hu']

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-12-13
    • 2021-01-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-27
    • 2020-07-02
    相关资源
    最近更新 更多