typescript
npm
开源项目
消息处理
Segment Matcher:高性能的消息段模式匹配库
一个类型安全、高性能的消息段模式匹配库,支持复杂的参数提取和智能空格处理
凉菜
作者
2025年11月8日
8 min read
项目简介
Segment Matcher 是一个专为消息段处理设计的高性能模式匹配库。它提供了类型安全的消息段匹配能力,支持复杂的参数提取、智能空格处理和丰富的类型系统,是开发聊天机器人和消息处理应用的理想选择。
一个类型安全、高性能的消息段模式匹配库,支持复杂的参数提取和智能空格处理
凉菜
作者
Segment Matcher 是一个专为消息段处理设计的高性能模式匹配库。它提供了类型安全的消息段匹配能力,支持复杂的参数提取、智能空格处理和丰富的类型系统,是开发聊天机器人和消息处理应用的理想选择。
Segment Matcher 提供了完整的类型系统来满足不同场景的需求:
支持多种参数定义方式:
<param:type>[param:type][param:type=default][...rest:type]使用 npm 安装:
npm install segment-matchernpm install segment-matcher或使用 yarn:
yarn add segment-matcheryarn add segment-matcher或使用 pnpm:
pnpm add segment-matcherpnpm add segment-matcherimport { SegmentMatcher } from 'segment-matcher';
// 创建消息段匹配器
const matcher = new SegmentMatcher('hello <name:text>');
// 匹配消息段
const segments = [
{ type: 'text', data: { text: 'hello Alice' } }
];
const result = matcher.match(segments);
if (result) {
console.log('匹配的消息段:', result.matched);
console.log('提取的参数:', result.params); // { name: 'Alice' }
console.log('剩余的消息段:', result.remaining);
}import { SegmentMatcher } from 'segment-matcher';
// 创建消息段匹配器
const matcher = new SegmentMatcher('hello <name:text>');
// 匹配消息段
const segments = [
{ type:
从单个连续文本段中自动提取多个参数:
const matcher = new SegmentMatcher('move [x:number=0] [y:number=0]');
// 自动从单个文本段提取参数
const result = matcher.match([
{ type: 'text', data: { text: 'move 10 20' } }
]);
console.log(result.params); // { x: 10, y: 20 }const matcher = new SegmentMatcher('move [x:number=0] [y:number=0]');
// 自动从单个文本段提取参数
const result = matcher.match([
{ type: 'text', data: { text: 'move 10 20'
word 类型可以提取多个单词参数,避免 text 类型的贪婪匹配:
const matcher = new SegmentMatcher('config [key:word=name] [value:word=default]');
const result = matcher.match([
{ type: 'text', data: { text: 'config database mysql' } }
]);
console.log(result.params); // { key: 'database', value: 'mysql' }const matcher = new SegmentMatcher('config [key:word=name] [value:word=default]');
const result = matcher.match([
{ type: 'text', data: { text: 'config database mysql' }
使用引号可以提取多个包含空格的 text 参数:
const matcher = new SegmentMatcher('post [title:text=Untitled] [tags:text=none]');
// 使用双引号
const result1 = matcher.match([
{ type: 'text', data: { text: 'post "My Article Title" "tag1 tag2 tag3"' } }
]);
console.log(result1.params);
// { title: 'My Article Title', tags: 'tag1 tag2 tag3' }
// 使用单引号
const result2 = matcher.match([
{ type: 'text', data: { text: "post 'Quick Tips' 'tutorial'" } }
]);
console.log(result2.params);
// { title: 'Quick Tips', tags: 'tutorial' }
// 嵌套不同类型引号
const result3 = matcher.match([
{ type: 'text', data: { text: `post "It's great" 'He said "hello"'` } }
]);
console.log(result3.params);
// { title: "It's great", tags: 'He said "hello"' }const matcher = new SegmentMatcher('post [title:text=Untitled] [tags:text=none]');
// 使用双引号
const result1 = matcher.match([
{ type: 'text', data: { text: 'post "My Article Title" "tag1 tag2 tag3"'
匹配特定类型的消息段:
const matcher = new SegmentMatcher('{text:hello}{at:123456}');
const result = matcher.match([
{ type: 'text', data: { text: 'hello' } },
{ type: 'at', data: { user_id: 123456 } }
]);
// 匹配成功,result 包含完整的消息段信息const matcher = new SegmentMatcher('{text:hello}{at:123456}');
const result = matcher.match([
{ type: 'text', data: { text: 'hello' }
收集所有剩余的同类型消息段:
const matcher = new SegmentMatcher('图片[...images:image]');
const result = matcher.match([
{ type: 'text', data: { text: '图片' } },
{ type: 'image', data: { file: '1.jpg' } },
{ type: 'image', data: { file: '2.jpg' } }
]);
// result.params.images 包含所有图片的信息const matcher = new SegmentMatcher('图片[...images:image]');
const result = matcher.match([
{ type: 'text', data: { text: '图片' }
自定义字段映射规则,按优先级提取值:
const matcher = new SegmentMatcher('图片<img:image>', {
image: ['url', 'file', 'src'] // 按优先级尝试这些字段
});
const result = matcher.match([
{ type: 'text', data: { text: '图片' } },
{ type: 'image', data: { url: 'https://example.com/image.jpg' } }
]);
// 按照 url -> file -> src 的优先级提取值const matcher = new SegmentMatcher('图片<img:image>', {
image: ['url', 'file', 'src'] // 按优先级尝试这些字段
});
const result = matcher.match
根据不同的使用场景,选择合适的参数类型:
| 场景 | 推荐类型 | 示例 | 说明 |
|---|---|---|---|
| 单个单词 | word | [name:word] | 不包含空格的字符串 |
| 包含空格的文本 | text + 引号 | [msg:text] 输入 "hello world" | 明确边界 |
| 最后一个参数 | text | [msg:text] | 贪婪匹配剩余内容 |
| 数字 | number | [count:number] | 整数或浮点数 |
| 整数 | integer | [age:integer] |
// 参数间的单个空格会被自动处理
const matcher = new SegmentMatcher('cmd [a:number] [b:number]');
// 以下两种输入都可以匹配
matcher.match([{ type: 'text', data: { text: 'cmd 10 20' } }]); // ✅
matcher.match([{ type: 'text', data: { text: 'cmd 1020' } }]); // ✅
// 多个空格会被视为字面量
const strictMatcher = new SegmentMatcher('cmd [a:number]'); // 两个空格
strictMatcher.match([{ type: 'text', data: { text: 'cmd 10' } }]); // ✅
strictMatcher.match([{ type: 'text', data: { text: 'cmd 10' } }]); // ❌// 参数间的单个空格会被自动处理
const matcher = new SegmentMatcher('cmd [a:number] [b:number]');
// 以下两种输入都可以匹配
matcher.match([{ type: 'text', data: { text: 'cmd 10 20' }
word 类型text + 引号text 类型放在参数列表末尾可以省略引号SegmentMatcher 实例// 定义机器人命令
const commandMatchers = {
help: new SegmentMatcher('help [command:word]'),
kick: new SegmentMatcher('kick {at:user}'),
ban: new SegmentMatcher('ban {at:user} [duration:integer=0]'),
config: new SegmentMatcher('config [key:word] [value:text]'),
search: new SegmentMatcher('search <query:text>'),
};
// 处理消息
function handleMessage(segments) {
for (const [name, matcher] of Object.entries(commandMatchers)) {
const result = matcher.match(segments);
if (result) {
console.log(`执行命令: ${name}`, result.params);
return;
}
}
console.log('未知命令');
}// 定义机器人命令
const commandMatchers = {
help: new SegmentMatcher('help [command:word]'),
kick: new SegmentMatcher('kick {at:user}'),
ban: new SegmentMatcher('ban {at:user} [duration:integer=0]'
// 解析富文本消息
const formatter = new SegmentMatcher(
'[...segments:text|at|image|emoji]'
);
const result = formatter.match([
{ type: 'text', data: { text: '你好 ' } },
{ type: 'at', data: { user_id: 123456 } },
{ type: 'text', data: { text: ' 看这张图片 ' } },
{ type: 'image', data: { url: 'example.jpg' } }
]);
// 格式化为 HTML
function formatToHTML(segments) {
return segments.map(seg => {
switch (seg.type) {
case 'text':
return seg.data.text;
case 'at':
return `<span class="at">@${seg.data.user_id}</span>`;
case 'image':
return `<img src="${seg.data.url}" />`;
default:
return '';
}
}).join('');
}// 解析富文本消息
const formatter = new SegmentMatcher(
'[...segments:text|at|image|emoji]'
);
const result = formatter.match([
{ type: 'text', data: { text
项目提供了完善的开发和测试支持:
# 运行测试
npm test
# 运行测试并生成覆盖率报告
npm run test:coverage
# 构建项目
npm run build
# 清理构建产物
npm run clean# 运行测试
npm test
# 运行测试并生成覆盖率报告
npm run test:coverage
# 构建项目
npm run build
# 清理构建产物
npm run cleanSegment Matcher 是一个功能强大、性能优异的消息段模式匹配库。它为开发者提供了:
无论是开发聊天机器人、消息处理系统,还是需要复杂的文本解析功能,Segment Matcher 都能提供简单、高效的解决方案。项目采用 MIT 许可证,欢迎社区贡献和反馈!
本文介绍的 Segment Matcher 项目是 zhinjs 组织开发维护的开源项目。如果这个项目对你有帮助,欢迎给项目点个 Star ⭐
Conversation
使用 GitHub 账号登录即可发表评论
登录后即可发表评论
| 只接受整数 |
| 浮点数 | float | [price:float] | 必须带小数点 |
| 布尔值 | boolean | [flag:boolean] | true/false |