← 中文资源

简体中文版本

Node.js 词数统计 CLI

报告文件行数、单词数和 UTF-8 字节数的小型命令行工具,包含验证输出与错误处理的单元和 CLI 测试。

阅读英文原文

项目说明

这是一个类似 wc 的最小 CLI,用于演示文件读取、字节计数和命令参数处理。

运行方法

执行 node wc.js file.txt,输出行数、单词数和 UTF-8 字节数。文件不存在时返回非零退出码并写入 stderr。

验证方式

测试使用固定文本断言三项计数,并覆盖空文件、多字节字符和缺失参数。注意“单词”按空白切分,对中文不适用;字节数按 UTF-8 而非字符数。工具只读取文件,不修改内容,适合作为脚本管道的一环。

验收清单

完成「Node.js 词数统计 CLI」后,按节点或操作步骤逐项自查:准备可复现的本地环境,执行文档中的命令,记录输出与失败信息,并确认权限、空数据和失败恢复路径都有对应证据。

代码示例

import { readFileSync } from 'node:fs';
import { pathToFileURL } from 'node:url';

export function countText(text) {
  const lines = text.split('\n').length;
  const words = (text.match(/\S+/g) ?? []).length;
  return { lines, words, bytes: Buffer.byteLength(text, 'utf8') };
}

if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
  const file = process.argv[2];
  if (!file) {
    console.error('usage: node cli.mjs <file>');
    process.exit(1);
  }
  console.log(JSON.stringify(countText(readFileSync(file, 'utf8'))));
}
import { test } from 'node:test';
import assert from 'node:assert/strict';
import { mkdtempSync, writeFileSync, rmSync } from 'node:fs';
import { join } from 'node:path';
import { tmpdir } from 'node:os';
import { spawnSync } from 'node:child_process';
import { countText } from './cli.mjs';

test('counts lines, words and bytes', () => {
  assert.deepEqual(countText('hello world\nsecond line\n'), { lines: 3, words: 4, bytes: 24 });
});

test('CLI prints JSON and rejects missing file', () => {
  const dir = mkdtempSync(join(tmpdir(), 'wc-'));
  const file = join(dir, 'sample.txt');
  writeFileSync(file, 'one two three\n');
  try {
    const ok = spawnSync(process.execPath, ['cli.mjs', file], { encoding: 'utf8' });
    assert.equal(ok.status, 0);
    assert.deepEqual(JSON.parse(ok.stdout), { lines: 2, words: 3, bytes: 14 });
    const bad = spawnSync(process.execPath, ['cli.mjs'], { encoding: 'utf8' });
    assert.equal(bad.status, 1);
  } finally {
    rmSync(dir, { recursive: true, force: true });
  }
});
node --test cli.test.mjs
printf 'one two three\n' > sample.txt
node cli.mjs sample.txt