python - 简单的 CSV 词法分析器

标签 python regex csv pygments

我想用 pygments 按列为 CSV 文件着色,如下所示:

enter image description here

看到同一列用相同的颜色着色。

目前 pygments 不包含 CSV 解析器,因为 CSV 是 said to be obscure format .所以我试着自己写一个最小的。这是我尝试过的:

tokens = {
    'root': [
        (r'^[^,\n]+', Name.Function), # first column
        (',', Comment),               # separator
        (r'[^,\n]+', Name.Decorator), # second column
        (',', Comment),               # separator
        (r'[^,\n]+', Name.Constant),  # third column
        (',', Comment),               # separator
    ],
}

但它无法为任何列着色,但首先:

enter image description here

据我所知,pygments 的工作原理是尝试一个接一个地匹配正则表达式:当当前正则表达式不匹配时——它会转到下一个,然后重新开始。如果没有任何匹配,它会发出错误并前进一个字符(并将该字符放在红色框中)。对于像嵌套评论这样的高级情况,有状态,但我认为对于 CSV 一个状态可能就足够了。

然后我尝试了:

tokens = {
    'root': [
        (',', Comment),                           # separator
        (r'^[^,\n]+', Name.Function),             # first column
        (r'(?:^[^,\n]+)[^,\n]+', Name.Decorator), # second column
    ],
}

但它会将所有列着色为第二列:

enter image description here

这是一个示例数据:

account_id,parent_account_id,name,status
,A001,English,active
A001,,Humanities,active
A003,A001,,active
A004,A002,Spanish,

在 Emacs 中,我设法得到了我想要的东西:

(add-hook 'csv-mode-hook
             (lambda ()
               "colors first 8 csv columns differently"
               (font-lock-add-keywords nil '(("^\\([^,\n]*\\),"
                                              1 'font-lock-function-name-face)))
               (font-lock-add-keywords nil '(("^\\([^,\n]*\\),\\([^,\n]*\\)"
                                              2 'font-lock-variable-name-face)))
               (font-lock-add-keywords nil '(("^\\([^,\n]*\\),\\([^,\n]*\\),\\([^,\n]*\\)"
                                              3 'font-lock-keyword-face)))
               (font-lock-add-keywords nil '(("^\\([^,\n]*\\),\\([^,\n]*\\),\\([^,\n]*\\),\\([^,\n]*\\)"
                                              4 'font-lock-type-face)))
))

(我其实加了4列以上,不过那不重要)

给出:

enter image description here

最佳答案

哦,我用状态解决了它:

tokens = {
    'root': [
        (r'^[^,\n]*', Name.Function, 'second'),
    ],
    'second': [
        (r'(,)([^,\n]*)', bygroups(Comment, Name.Decorator), 'third'),
    ],
    'third': [
        (r'(,)([^,\n]*)', bygroups(Comment, Name.Constant), 'fourth'),
    ],
    'fourth': [
        (r'(,)([^,\n]*)', bygroups(Comment, Name.Variable), 'fifth'),
    ],
    'fifth': [
        (r'(,)([^,\n]*)', bygroups(Comment, Keyword.Type), 'unsupported'),
    ],
    'unsupported': [
        (r'.+', Comment),
        ],
}

它以不同的方式为前 5 个 CSV 列着色,并为所有其他列着色:

enter image description here

关于python - 简单的 CSV 词法分析器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25501936/

相关文章:

python - 如何在python中用 celery 清除特定队列的所有任务?

regex - HiveQL:从字符串中删除句点

regex - 正则表达式捕获和反向引用

python - 在 python 2.7 中打开空格(?)分隔的文本文件?

python - 按数据框中的日期过滤数据

python - 如何使用 python 执行具有多个动态参数的 postgres 查询

python - 将非常大的 RDF 三元组加载到 iGraph -> 快速顶点查找?

python - 如何在 Python 中获得毫秒和微秒分辨率的时间戳?

c - 正则表达式.h : print the subexpression

python - Mutt 不附加多个文件并将附件发送到 python 中的服务器