CSV转Markdown表格转换器

按 RFC 4180 解析 CSV 后输出 GFM 表格:引号内的逗号与换行不当作分隔符,字段内部的双引号写作连续两个。输出用竖线分隔每个单元格,表头下方必须补一行分隔行,数值列自动右对齐、文本列左对齐。单元格里的竖线转义成反斜杠竖线,换行转成 br 标签。附二十行转义速查表与 CSV 导出,全程本地计算不上传。

按 RFC 4180 解析:引号内的逗号与换行不拆分字段,内部双引号写作连续两个。

默认示例是 4 行 3 列的 CSV,第二行含被引号包裹的逗号、第三行含转义双引号。输入框被清空时点「转为表格」会自动填回示例;在表头行数或阈值输入框里按 Enter 也会重新转换。

使用方法

  1. 「CSV 源数据」默认已经写好四行,第一行是表头 name,score,note,第二行的备注里含一个被引号包裹的逗号,第三行的备注里含一对转义双引号。
  2. 「表头行数」默认 1,可填 0 到 2。填 0 表示源数据没有表头,工具会生成一行空表头;填 2 表示前两行都当表头,只取第二行作为列名。
  3. 「数值列判定阈值」默认 100,单位百分比。某一列的非空单元格里,能被解析成数字的比例不低于这个阈值,就判为数值列并右对齐。
  4. 「对齐方式」默认自动。选左、居中或右会覆盖自动判定,把全部列统一成一种对齐。
  5. 按 Ctrl+Enter(Mac 上 Cmd+Enter)或在上方任一输入框里按回车即可转换。
  6. 结果区第一行是主结果行数与列数,下面是可直接粘进 Markdown 的表格原文,最后一行统计转义了几处竖线、几处换行。
  7. 下方是二十行转义速查表,默认显示 12 行,点「加载更多」展开余下 8 行;「导出 CSV」存成带字节序标记的文件。
  8. 源数据为空、引号不闭合、各行列数不一致、表头行数超过总行数、两个数字输入越界或不是整数,都会给出写明行号或字段名与原因的具体提示。

这个CSV转Markdown表格工具能解决什么

把表格数据从 Excel 或数据库导出成 CSV 后,要放进 README、issue 或文档站点,就得改写成 Markdown 表格。手写的工作量不大,但转义规则繁琐:单元格里出现竖线会撑破列、出现换行会让表格断行、出现逗号又容易在二次编辑时出错。这一页做的是按 RFC 4180 把 CSV 正确切成行列,再按 GFM 的规则逐格转义输出。

第一类是日常的 README 表格。四行三列的源数据粘进来,输出 | name | score | note | 打头、第二行是分隔行,直接贴进 .md 文件就能渲染。score 这一列全是数字,自动判为数值列写成 ---:,其余列保持左对齐。

第二类是含特殊字符的数据。备注里写「含, 逗号」,如果不加引号,CSV 会把它切成两列;加了引号,本页解析后仍然是一个完整的单元格。备注里写「含"引号"」,源数据里必须写成两个连续双引号,本页解析时还原成一个——这一步最容易在二次编辑时被破坏,因此结果区会统计转义次数供核对。

第三类是排版细节。GFM 要求表头下方必须有分隔行,否则整段会被当成普通段落;单元格里的竖线要写成 \| 才能显示为字面竖线;单元格里的换行在表格里无法表示,只能换成 <br>。这三条规则本页全部自动处理。

还有一类边界要说清:本页只做格式转换与转义,不做数据校验,合并单元格、跨行表头、单元格内的 Markdown 语法都不在支持范围内。

计算原理与变量说明

解析部分是一个双状态扫描器:状态「在引号内」与「在引号外」。引号外的逗号结束当前字段、换行结束当前行;引号内两者都只是普通字符,唯一需要特殊处理的是连续两个双引号,它代表一个字面双引号。扫描结束后把最后一个字段与最后一行收尾,并丢弃文件末尾多余的空行。

为什么必须用状态机而不是 split。按逗号切分无法区分「字段分隔的逗号」与「字段内容里的逗号」。RFC 4180 规定后者必须整段用双引号包裹,只有维护「是否在引号内」这个状态才能正确还原字段。

变量含义取值影响
hd表头行数0、1、2 的整数决定哪一行当列名,0 时补空表头
thr数值列阈值0 ~ 100 的整数非空数字占比达标即右对齐
am对齐方式auto / left / center / right非 auto 时统一覆盖自动判定
w表格列数各行列数的最大值短行补空,长行截断到表头列数
iq引号状态true 表示处于引号内解析结束时仍为 true 即引号不闭合
n转义计数非负整数统计竖线与换行被替换的次数

输出只做三处改动。一是单元格里的竖线替换成 \|;二是换行(\n、\r\n、\r 都算)替换成 <br>;三是列宽统一,以表头列数为准,缺的补空、多的丢弃。其余原样保留,不做 trim。

对齐靠分隔行而不是单元格。GFM 的对齐写在表头下方那一行的冒号位置:左对齐 :---、居中 :---:、右对齐 ---:、不指定 ---。它管的是整列,所以「数值列右对齐」是给那一列的分隔格写 ---:,而不是给每个数字加空格。

数值列的判定用正则而不是 Number()。因为 Number("")、Number(" ")、Number("1,2") 在 JS 里的行为各不相同,直接用它判断会把空串和千分位写法误判成数字。本页用 /^[+-]?(\d+(\.\d*)?|\.\d+)([eE][+-]?\d+)?$/ 先做形状检查,只有形状合规才计入数值计数。

表头只能取一行。分隔行只有一行,多行列名在 GFM 里无法表达;表头行数填 2 时取第二行当列名,第一行丢弃,是为兼容导出时多带的一行标题。

完整示例(数值仅作演示)

默认源数据四行三列:表头 name,score,note,数据三行。第二行备注 "含, 逗号" 因含逗号而被引号包裹,解析后是一个单元格,内容为「含, 逗号」;第三行备注 "含""引号""" 里的两处连续双引号各还原成一个字面双引号,得到「含"引号"」。

源:name,score,note
  "含, 逗号"   → 一个字段,内容是「含, 逗号」
  "含""引号"""  → 一个字段,内容是「含"引号"」
列判定:score 列 3 个非空值全部匹配数字正则 → ---
输出:| name | score | note |
   | --- | ---: | --- |

把「表头行数」改成 0,输出会在数据上方补一行空表头,数据仍是三行;改成 2,则取第二行当列名,第一行数据被丢弃。把阈值从 100 改成 60,score 列仍然 3/3 达标;若某列三个格子里只有两个是数字,占比约 66.7%,阈值 60 时判为数值列,阈值 100 时不判。

把「对齐方式」改成居中,全部列都会写成 :---:。源数据里填一行只有两个字段的记录,会提示第几行列数不符——这是 CSV 最常见的错误,二次编辑时最容易漏掉引号。

转义规则速查表

下表列出二十种单元格内容经过本页转义后的结果,由页面自己的转义函数逐格生成,可以直接对照。需要改写的只有竖线与换行两种字符,其余一律原样保留。

原始单元格输出单元格说明
abcabc普通文本不做任何改动
a,ba,b逗号来自引号内,转义阶段原样保留
a"ba"b双引号已在解析阶段还原成一个
a\nba<br>b换行在表格里无法表示,转成 br 标签
a|ba\|b字面竖线必须转义,否则会多出一列
价格|数量价格\|数量表头里的竖线同样要转义
1\n21<br>2两行文本合并成一个单元格
50%50%百分号不是特殊字符
#3498DB#3498DB井号只在行首才是标题
含,逗号和|竖线含,逗号和\|竖线两种特殊字符同时出现
x x 前后空格原样保留
(空)(空)空字段输出为空单元格

第二张表给出对齐写法与列判定的对应关系,以及分隔行缺失时的后果。

写法含义适用列
---不指定对齐默认,渲染器自行决定
:---左对齐文本列
:---:居中短枚举值
---:右对齐数值列
无分隔行整段不渲染为表格检查表头下是否漏了这一行

结果边界、舍入与适用说明

常见问题

为什么不能直接按逗号切分?

因为 RFC 4180 允许字段内容里含逗号,只要整段用双引号包裹即可。按逗号切分无法区分这两种逗号,会把一个字段拆成两列。

字段里的双引号为什么要写两个?

因为双引号本身是包裹符。要在内容里表示一个字面双引号,就得写成连续两个,解析器在引号内遇到两个连续双引号时还原成一个。这是 RFC 4180 的规定,不是本页自创。

单元格里的换行会怎样?

会被转成 br 标签。GFM 表格的每一行必须写在一行文本里,物理换行会终止整个表格,所以只能用 br 标签表达单元格内的软换行。

数值列是怎么判出来的?

统计该列非空单元格中能被数字正则匹配的比例,比例不低于阈值就判为数值列。阈值默认 100,表示整列必须全是数字才右对齐。

分隔行是什么,漏了会怎样?

是表头下方那一行由连字符与可选冒号组成的行。GFM 靠它判定上面那行是表头、下面是数据;漏掉它,整段会被当成普通段落原样显示。

能把制表符分隔的数据粘进来吗?

不能。本页只认 RFC 4180 的逗号分隔格式;制表符分隔的数据会被当成普通字符留在同一格里。请先在表格软件里另存为 CSV。

生成结果能在哪些地方渲染?

GitHub、GitLab、多数静态站点生成器与常见 Markdown 编辑器都支持 GFM 表格语法。少数老式解析器不支持对齐冒号,此时分隔行会被忽略但表格仍能显示。

输入的数据会上传到服务器吗?

不会。解析、转义、拼表与导出全部在本页 JavaScript 里完成,没有发起任何网络请求,刷新即恢复默认示例。

相关工具