行统计

只看「行」:粘贴文本即给出文本行数、非空行、空白行、最长行、平均行长与换行符总数,并把 CRLF、LF、单独 CR 分开计数。末尾换行算不算一行、为什么 split 会多出一个空元素,都在下面写清楚。

文本行数6
非空行5
空白行1
最长行(字符)23
平均行长8.50
换行符总数5

统计随输入自动完成,不需要点按钮;文本很长时在输入框里按 Ctrl + Enter(macOS 用 Cmd + Enter)可以立刻重算一次,Enter 本身留给换行。

文本片段split 长度文本行数非空行最长行说明
空串1000空串按文本行数算 0 行,split 却给出 1 个空元素
a1111没有换行符,就是 1 行
a\n2111末尾换行只说明第 1 行已终止,不新增空行
a\nb2221无终止符,两行都是完整行
a\nb\n3221与 a\nb 行数相同,split 却多出一个空元素
a\nb\nc3331两个换行符对应 3 行
\n2100一个空行,split 得到 2 个空元素
\n\n3200两个空行
a\n\nb3321中间是空白行,非空行只有 2
\n 2203只有空格的行算空白行,但仍计入文本行数
a\r\nb2221CRLF 若只按 \n 切,首行会残留 \r 让最长行多 1
a\r\nb\r\n3221CRLF 同样多出末尾空元素,行数口径不变

这张表把「换行写法」和「统计结果」摆在一起:同样的两行文本,写成 a\nb 还是 a\nb\n,最长行都是 1,但 split 长度差 1;从 Windows 记事本复制过来的文本多为 CRLF,不处理 \r 就会让每一行都多算 1 个字符。

使用方法

  1. 把文本粘进上面的框,或直接输入。结果是实时更新的,页面打开时框里已有一段 6 行的示例,卡片上显示的就是它的结果。
  2. 看文本行数判断篇幅:示例是 6 行。这个数字已经按「末尾换行不额外算一行」的口径处理过。
  3. 看非空行(示例 5)与空白行(示例 1):第 4 行是空行,所以两者相加正好回到 6。
  4. 看最长行(示例 23 个字符)与平均行长(8.50),用来判断有没有某一行特别长、需不需要折行。
  5. 看换行符总数(示例 5)以及下方提示里的 CRLF / LF 拆分,确认文本是从哪个系统复制来的。
  6. 点「复制统计结果」带走六项指标;「载入示例」还原样例,「清空文本」清空,输入框里按 Ctrl + Enter 可跳过延迟立刻重算。

这个行统计能解决什么问题

一是核对「行数对不上」。同一份名单在一个系统显示 120 行、另一个显示 121 行,绝大多数情况是末尾那个换行符被当成了空行。本页把「文本行数」和「split 长度」两个口径同时摆出来,一眼就能看出差异来自哪里。

二是处理从 Windows Office 粘过来的数据。Windows 记事本、Excel 复制的多行文本用的是 CRLF(回车加换行),纯 \n 切分会把 \r 留在行尾,最长行、平均行长都会整体偏大。本页先做换行归一,再把 CRLF、LF、单独 CR 三类换行符分别报数。

三是清理粘贴带来的空白行。空白行数一栏直接告诉你混进来几行空内容;要把它们删掉,可以用页面下方的「删除空行」工具,不用手动一行行找。

四是给排版和导入做体检。导入 CSV 前先看行数和最长行,能提前发现多余换行、断裂的记录;日志文件按行统计总行数,也常用作数据量的粗略刻度。

本页不做这些事:不统计汉字、单词、句子和段落(那些是另一个口径,请用「字数统计工具」);不按字节算长度(请用「字符数统计工具」);也不修改文本本身,去空行、去重复行都有专门的工具。

统计原理:按行拆分的三种口径

第一步是把换行归一。本页用 x.split(/\r\n|\r|\n/) 切行,而不是常见的 x.split('\n')。差别在 CRLF:Windows 文本的换行是两个字符 \r\n,若只按 \n 切,每一行末尾都会留下一个不可见的 \r,于是 第一行 会变成 第一行\r,最长行长度从 3 变成 4。正则的写法里 \r\n 必须放在最前面,否则 \r 会先把 CRLF 拆成两段,反而多切一次。

第二步是区分「split 长度」与「文本行数」。这是行统计最容易踩的坑:'a\nb\n'.split('\n') 得到 ['a', 'b', ''],长度是 3,但这份文本其实只有 2 行——最后那个空字符串只是因为字符串以换行符结尾。本页的「文本行数」按后者算:若最后一个元素是空串,就把它减掉;若文本本身是空串,则算 0 行。这也是为什么空串的 split 长度是 1、文本行数却是 0。

第三步是判定空白行。用 L[i].trim() === '' 判断:只含空格、制表符的行按空白行计,但仍占一行。示例文本第 4 行是真正的空行,第 10 行对照里的 \n 则是两行「只有空格的行」,两者都计入文本行数、都不计入非空行。

换行符计数分开做三档。LF 用 /\n/g,CRLF 用 /\r\n/g,单独 CR 用 /\r(?!\n)/g(负向前瞻,确保这个 \r 后面不是 \n)。总数 = 单独的 LF + CRLF + 单独的 CR。这样报出来的数字既不会把 CRLF 里的 \n 重复计一次,也不会漏掉老 Mac 文本里的孤立 \r。

行长按 Unicode 码点算。用 Array.from(line).length 而不是 line.length:JavaScript 字符串以 UTF-16 存储,一个 emoji 或扩展区生僻字占 2 个码元却只有 1 个码点。行统计关心的是「这一行看起来有多长」,用码点更贴近直觉;若你要的是存储字节数,那属于另一套口径。换行符依据的是 Unicode 的行终结符定义,ECMAScript 的字符串语义由 ECMA-262 规定,两者都不随版本频繁变动,可以照页面上的写法自行复核。

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

示例条件就是页面打开时框里那段文字,共 6 行、中间夹一行空行、结尾不带换行符。复算结果如下:

  • 文本行数 6、非空行 5、空白行 1;
  • 最长行 23 个字符,出现在第 2 行「第 2 行故意写长一点,用来演示最长行的口径。」;
  • 平均行长 8.50,即 6 行长度之和 51 除以 6;
  • 换行符总数 5,全部是 LF,CRLF 与单独 CR 均为 0;
  • 因为结尾没有换行符,所以 split(/\r\n|\r|\n/) 的长度也是 6,与文本行数相等,末尾没有多出空元素。

逐行长度可以手工对一遍:第 1 行 7、第 2 行 23、第 3 行 6、第 4 行 0、第 5 行 5、第 6 行 10,合计 51,最长 23,平均 51 ÷ 6 = 8.50。两个边界例子更能说明口径:a\nb\n 的 split 长度是 3 而文本行数只有 2;从记事本复制的三行文本 第一行\r\n第二行\r\n第三行,若错误地按 \n 切,最长行会从 3 变成 4——多的就是那个残留的 \r。

换行写法与统计口径对照表

下表把常见文本片段的统计结果列出,split 长度 是按 \n 直接切分的直观值,文本行数 是本页采用的规范口径。两列不一致时,以「文本行数」为准。

文本片段split 长度文本行数非空行最长行说明
空串1000空串按文本行数算 0 行,split 却给出 1 个空元素
a1111没有换行符,就是 1 行
a\n2111末尾换行只说明第 1 行已终止,不新增空行
a\nb2221无终止符,两行都是完整行
a\nb\n3221与 a\nb 行数相同,split 却多出一个空元素
a\nb\nc3331两个换行符对应 3 行
\n2100一个空行,split 得到 2 个空元素
\n\n3200两个空行
a\n\nb3321中间是空白行,非空行只有 2
\n 2203只有空格的行算空白行,但仍计入文本行数
a\r\nb2221CRLF 若只按 \n 切,首行会残留 \r 让最长行多 1
a\r\nb\r\n3221CRLF 同样多出末尾空元素,行数口径不变

再看换行符本身的对照。识别出用的是哪一种换行,是判断文本来源最快的方法:

换行写法字符典型来源只按 \n 切会怎样
LF\n(U+000A)Linux、macOS、多数网络协议正常,行尾无残留
CRLF\r\n(U+000D U+000A)Windows、记事本、Excel 复制、HTTP 头每行尾部残留 \r,行长整体 +1
CR\r(U+000D)经典 Mac OS 9 及更早整段被当成一行,行数严重偏少

输入范围、边界与精度说明

  • 文本上限 100 万字符(输入框的 maxlength,按 UTF-16 码元计)。纯汉字能装 100 万个,纯表情只能装约 50 万个。超过 50 万字符时输入会有一点延迟,按 Ctrl + Enter 可立刻重算一次。
  • 空文本时六项全是 0,包括空白行与最长行;页面不会给出「1 行」这种看着就不对的默认值,而是显示一段说明,告诉你 split 长度为何是 1。
  • 「文本行数」与「split 长度」相差最多 1。差值恰好为 1 当且仅当文本以换行符结尾;若结尾没有换行符,两者相等。这正是「末尾要不要算一行」这个争议的全部来源。
  • 只有空白时不算非空行,但仍算行。三个空格加一个换行,结果是「文本行数 2、非空行 0、空白行 2、最长行 3」。
  • 行长按码点计,一个 emoji 算 1。用 Array.from(line).length。若你要的是数据库字段能装多少字节,那是 UTF-8 字节口径,一个汉字 3 字节、一个 emoji 4 字节,请用字符数统计工具。
  • CR 单独出现时按一次换行处理。老 Mac 文本用孤立 \r 表示换行,正则里的 \r 分支专门兜住它;不处理的话整段会被算成 1 行。
  • 不做 Unicode 其他行终结符。Unicode 还定义了 U+2028 行分隔符与 U+2029 段分隔符,但它们极少出现在普通文本里,本页不把它们当换行,以免把某些特殊字符内容误切。
  • 不改动你的文本。归一化只在内存里做一份副本用于统计,输入框里的原文原样保留,也不会写回或上传。

常见问题

为什么行数比我在编辑器里看到的多 1?

多半是末尾多了个换行符。很多编辑器不显示行尾换行,但文本其实以 \n 结尾,某些统计方式会把最后那个空串也算成一行。本页的「文本行数」不会把它算进去:结尾有换行时,split 长度是行数加 1,我们把这个多出来的空元素减掉。对照表里 a\nb 与 a\nb\n 两行就能看出这一点。

从 Excel 或记事本复制过来,最长行怎么变长了?

因为那些文本用的是 CRLF 换行。若只按 \n 切分,每一行末尾都会留一个不可见的 \r,行长整体加 1。本页先用 /\r\n|\r|\n/ 归一,再统计,所以最长行、平均行长都不会被 \r 污染。下方提示里会单独报出 CRLF 的个数,方便你确认来源。

「文本行数」和「split 长度」到底该信哪个?

看你要回答什么问题。如果你问「这份文本有多少行内容」,用文本行数——它把末尾终止符造成的那一行排除掉。如果你问「按 \n 切开会得到几个数组元素」,用 split 长度。两者最多差 1,差值出现就说明文本以换行符结尾。本页把两个数都摆出来,就是让你按需要取用。

只有空格的行算不算空行?

算空白行,但仍计入文本行数。判定用的是 trim() 后是否为空,所以「三个空格」和「一个制表符」这样的行都归入空白行,不会进非空行。要把它们连同空行一起清掉,用「删除空行」工具即可。

换行符总数和行数是什么关系?

对结尾带换行的文本,换行符总数正好等于文本行数;对结尾不带换行的文本,换行符总数等于文本行数减 1。示例文本结尾没有换行,6 行对应 5 个换行符,正好符合这个关系,可以用它快速自查统计有没有跑偏。

一个表情或生僻字会让行长多算吗?

不会。行长按 Unicode 码点计,一个 emoji 只算 1。若按 JavaScript 的 line.length(UTF-16 码元)数,一个 emoji 会被算成 2。两种口径都有用途,本页选了更贴近「看起来多长」的码点口径,并在说明里注明。要按字节数衡量,请改用字符数统计工具。

它和字数、字符数统计有什么区别?

这个行统计只回答「行」的问题:多少行、几行是空的、最长行多长。字数统计工具数的是汉字、单词、段落,字符数统计工具数的是字符与字节。日志、名单、导入前的 CSV 这类以行为单位的数据,用行统计更快;文章投稿、文案字数核对,用字数统计更对。

文本会被上传或保存吗?

不会。六项指标全部由页面里的正则与字符串运算算出,没有任何网络请求,也不写入浏览器存储,刷新页面后输入框回到那段 6 行的预置示例。想自己确认,可以打开开发者工具的 Network 面板,边输入边看有没有请求发出。

相关工具