稿件字数对账
自由译者接了一篇 1.2 万字的英译中稿件,客户按中文字数计费。翻译完成后,客户用 Word 统计说只有 1.1 万字,要扣费。译者用本工具(Unix wc 风格)重新统计,发现客户把英文单词数和中文混算了。本工具严格区分字符、词、行,不依赖排版格式,给出纯文本的精确字数,帮译者拿回应得的 1000 元。
写完一段代码,想确认注释行和空行各占多少,或者收到一份合同,需要按行数计费——手动数不现实,全选复制到 Word 看字数又太慢。这个工具直接统计行数、词数和字符数,结果与 Unix `wc` 命令一致,包括对多行空行和末尾换行的处理方式。所有文本只留在浏览器本地,不上传任何数据。
自由译者接了一篇 1.2 万字的英译中稿件,客户按中文字数计费。翻译完成后,客户用 Word 统计说只有 1.1 万字,要扣费。译者用本工具(Unix wc 风格)重新统计,发现客户把英文单词数和中文混算了。本工具严格区分字符、词、行,不依赖排版格式,给出纯文本的精确字数,帮译者拿回应得的 1000 元。
团队 Git 仓库规定单次提交的代码变更行数不得超过 300 行,防止大段无注释代码混入。开发者在 `git diff` 后,将差异文本粘贴到本工具,直接看到纯增删行数(不含空行和注释)。上周有同事提交了 487 行,靠本工具提前发现并拆分为两次提交,避免了 Code Review 被驳回。
医学期刊要求中文摘要严格控制在 300 字以内,超出 1 字直接退修。研究生写完摘要后,用 Word 统计显示 298 字,但投稿系统提示超限。用本工具(Unix wc 风格)一查,发现 Word 把英文药物名中的连字符算成了两个字符,实际是 305 字。按本工具统计结果删改后,一次过审。
公司计划采购 10 篇新闻稿用于媒体分发,服务商按「字符数(不计空格)」报价,每千字 200 元。编辑写完初稿后,用本工具统计出正文 1850 字符(不计空格),但服务商报来的账单显示 2100 字符。用本工具逐段比对,发现对方把标题、作者署名、文末免责声明都算进去了。最终按本工具结果重新议价,节省了 50 元/篇。
出版社在整理《左传》校注本,要求每个校注段落对应的原文行数必须与底本一致(每页 20 行)。编辑将扫描件 OCR 后,发现自动换行导致段落错乱。用本工具统计每段原文的行数,与底本逐行比对,发现第 7 段 OCR 多断了一行(21 行 vs 20 行)。修正后,全书排版不再出现跨页断注的问题。
| 维度 | 本工具 | 竞品 A(在线 wc 类网站) | 传统方法(本地终端 wc 命令) |
|---|---|---|---|
| 隐私 | 纯浏览器处理,文件不离开本地 | 多数需上传文件到服务器 | 完全本地,无网络传输 |
| 离线可用 | 浏览器加载后完全离线可用 | 需联网,无网络无法使用 | 终端自带,完全离线 |
| 大小限制 | 受浏览器内存限制,大文件可能卡顿 | 受服务器上传限制,通常 10-50MB | 无限制,取决于系统资源 |
| 平台 | 任何现代浏览器(PC / 移动端) | 浏览器,但部分需注册 | 仅限桌面系统(Linux / macOS / Windows 终端) |
| 操作门槛 | 打开即用,无需安装或命令 | 打开即用,但部分有广告或注册 | 需熟悉命令行,输入 wc 命令 |
| 输出格式 | 结构化表格展示,可复制 | 通常纯文本输出 | 纯文本输出,需自行格式化 |
| 输入 | 输出 | 说明 |
|---|---|---|
| Hello world This is a test. | 2 lines, 5 words, 25 characters | 常规:两行英文,验证行/词/字符基本计数,词数按空格分隔,字符含换行符 |
| 行数 统计 工具 | 3 lines, 3 words, 9 characters | 常规:三行中文,每个汉字算一个字符,无空格时词数等于行数(每行一个词) |
| 0 lines, 0 words, 0 characters | 边界:空输入,验证工具不会报错或返回空串,所有计数为0 | |
| 1 line, 0 words, 3 characters | 边界:仅空格,词数为0(空格不构成词),字符数含空格,行数仍为1 | |
| a b | 3 lines, 2 words, 4 characters | 边界:中间有空行,空行计为一行,词数只统计非空行中的词 |
| Hello world Line2 | 2 lines, 3 words, 17 characters | 易错:含制表符,制表符算一个字符,词数按空白字符(空格/制表符)分隔,易被误认为多词 |
| leading spaces leading spaces | 2 lines, 4 words, 31 characters | 易错:每行前有空格,空格计入字符数但不影响词数,行首空格不产生额外词 |
1.把换行符当成空行计入行数
文本末尾有一个空行,统计结果多一行在输入前用文本编辑器去掉末尾空行,或确认工具是否默认忽略末尾空行Unix wc 默认将文件末尾换行符视为一行结束,因此末尾空行会计入行数。多数在线工具沿用此行为,需用户自行判断是否包含末尾空行。
2.中英文混排时词数统计偏差
输入 'hello世界',期望词数为 2(hello 和 世界)输入 'hello 世界',中间加空格wc 风格按空格/制表符/换行符分词。中文连续字符无分隔符时会被视为一个词。若需按语义分词,应使用支持中文分词的工具。
3.特殊 Unicode 字符被拆成多个字符
输入 emoji 😊,期望字符数为 1,实际显示 2确认工具统计的是 Unicode 码点还是字形簇(grapheme cluster)😊 由 2 个码点(U+1F60A + U+FE0F)组成,若工具按码点统计则显示 2。wc 默认按字节或码点,不合并变体选择符。
4.制表符宽度影响列对齐判断
用制表符对齐表格,统计行数后以为每行长度相同将制表符替换为空格后再统计字符数制表符在终端中宽度可变(通常 8 列),但字符统计只计 1 个字符。若需精确列宽,应展开为空格。
5.混合换行符导致行数不一致
Windows 下编辑的文本(CRLF)上传到 Linux 工具,行数比预期多统一换行符为 LF(Unix)或 CRLF(Windows)后再统计wc 按换行符(\n)计数,CRLF(\r\n)中的 \r 不被视为换行,但部分工具可能将 \r 视为额外字符,导致显示偏差。
6.忽略 BOM 头对字符数的影响
UTF-8 文件带 BOM(EF BB BF),字符数多出 3 个保存为 UTF-8 without BOM,或确认工具是否自动跳过 BOMBOM 是文件开头的 3 字节标记,部分工具将其计入字符数。wc 默认计入,需用户预处理。
字符数 = 行数 × 平均每行字符数(含换行符)
行数文本总行数,含空行平均每行字符数每行字符数均值,含空格和换行一段文本共 3 行:'Hello'(5 字符+换行)、'World'(5 字符+换行)、'!'(1 字符+无换行)。总字符数 = 5+1 + 5+1 + 1 = 13。行数=3,平均每行≈4.33 字符。
6 种主流语言实现,复制即用:
import sys
# 从 stdin 读取内容,输出行数、单词数、字符数(wc 风格)
text = sys.stdin.read()
lines = text.count('\n')
words = len(text.split())
chars = len(text)
print(f"{lines} {words} {chars}")// 浏览器环境,从 textarea / 字符串计算
function wc(text) {
const lines = (text.match(/\n/g) || []).length;
const words = text.trim() ? text.trim().split(/\s+/).length : 0;
const chars = text.length;
return { lines, words, chars };
}
// 示例
console.log(wc("hello world\nfoo bar\n")); // { lines: 2, words: 4, chars: 20 }package main
import (
"bufio"
"fmt"
"os"
"strings"
)
func main() {
scanner := bufio.NewScanner(os.Stdin)
var lines, words, chars int
for scanner.Scan() {
line := scanner.Text()
lines++
words += len(strings.Fields(line))
chars += len(line) + 1 // +1 for newline
}
fmt.Printf("%d %d %d\n", lines, words, chars)
}#!/bin/bash
# 等效于 wc 命令,输出行数、单词数、字符数
# 用法: ./wc.sh < file.txt 或 echo "text" | ./wc.sh
while IFS= read -r line; do
((lines++))
# 用 awk 统计单词数(按空白分割)
words_on_line=$(echo "$line" | awk '{print NF}')
((words += words_on_line))
((chars += ${#line} + 1)) # +1 算换行符
done
# 处理最后一行无换行的情况
if [[ -n $line ]]; then
((chars--)) # 最后一行没有换行符
fi
echo "$lines $words $chars"use std::io::{self, Read};
fn main() -> io::Result<()> {
let mut text = String::new();
io::stdin().read_to_string(&mut text)?;
let lines = text.lines().count();
let words = text.split_whitespace().count();
let chars = text.chars().count();
println!("{} {} {}", lines, words, chars);
Ok(())
}import java.io.BufferedReader;
import java.io.InputStreamReader;
public class Wc {
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringBuilder sb = new StringBuilder();
String line;
while ((line = br.readLine()) != null) {
sb.append(line).append('\n');
}
String text = sb.toString();
int lines = text.isEmpty() ? 0 : text.split("\n", -1).length - 1;
int words = text.isEmpty() ? 0 : text.trim().split("\\s+").length;
int chars = text.length();
System.out.println(lines + " " + words + " " + chars);
}
}本工具遵循 Unix wc 风格,按换行符(\n)计数,空行也包含一个换行符,因此会计入行数。如果你不希望统计空行,可以先在编辑器中删除空行再粘贴。统计结果会同时显示总行数和非空行数,方便对比。
常见原因是编辑器显示换行方式不同。比如 Windows 记事本用 CRLF(\r\n),而本工具按 Unix 标准只认 LF(\n)。另外,部分编辑器在文件末尾自动添加换行符,工具会统计这一行,但编辑器可能不显示。建议先检查粘贴内容末尾是否有空行,或者用“显示所有字符”功能确认换行符格式。
本工具字符统计按 Unicode 字符数计算,每个汉字、英文字母、标点符号、空格都算一个字符。这与 Word 等软件按“字符数(不计空格)”不同。如果你需要统计中文字数(不含标点和空格),可以结合工具输出的“字符数”和“非空字符数”自行计算,或使用专门的“中文字数统计”工具。
本工具在浏览器本地运行(纯前端实现),处理几万字文本完全无压力,实测 10 万字文本可在 1 秒内完成统计。理论上受浏览器内存限制,但普通用户日常使用(几十万字以内)不会遇到问题。如果粘贴后页面无响应,建议分段粘贴或检查是否有异常字符。
本工具完全在浏览器本地执行,文本不会离开你的设备,无需担心隐私泄露。统计结果也是本地生成,不涉及任何网络请求。你可以断网测试,工具依然正常工作。适合处理敏感数据,如密码列表、代码片段、合同文本等。
本工具按空格和标点分隔来统计词数(近似 Unix wc -w 逻辑),而 Word 使用更复杂的自然语言算法(如连字符、缩写、数字组合等有特殊处理)。例如“3.14”在本工具中算 1 个词,Word 可能算 1 个或 2 个。如果你需要与 Word 完全一致,建议在 Word 内查看统计。
当前版本不支持选择范围统计。如需统计部分行,建议先在文本编辑器中截取该范围文本(如第 5-10 行复制出来),再粘贴到本工具中统计。未来版本可能增加“统计选中区域”功能,但目前请手动分段操作。
会的。所有空格(包括缩进、行首行尾空格)都会计入字符数。如果你需要统计“有效字符数”(不含空格),可以看“非空字符数”字段,它只统计非空格、非换行的可见字符。代码统计场景中,建议关注“非空字符数”以忽略格式空格。
隐私保证所有计算与处理均在你的浏览器本地完成,输入数据不会上传服务器,也不会保存或共享。