golang高效解析任意字符串、切片和无限缓冲区的分词插件库tokenizer的使用

Golang高效解析任意字符串、切片和无限缓冲区的分词插件库tokenizer的使用

Tokenizer是一个高性能的Golang库,用于解析任意字符串、切片和无限缓冲区为各种标记(tokens)。它具有以下主要特性:

主要特性

  • 高性能
  • 不使用正则表达式
  • 提供简单API
  • 支持整数和浮点数
  • 支持带引号或其他"框架"的字符串
  • 支持在带引号或"框架"字符串中的注入
  • 支持Unicode
  • 可自定义标记
  • 自动检测空白符号
  • 可解析任何数据语法(xml、json、yaml)和编程语言
  • 单次数据遍历
  • 可解析无限传入数据且不会panic

使用场景

  • 解析html、xml、json、yaml等文本格式
  • 解析大型或无限文本
  • 解析任何编程语言
  • 解析模板
  • 解析公式

基本用法示例

解析SQL WHERE条件

import "github.com/bzick/tokenizer"

// 定义自定义标记键
const (
	TEquality = iota + 1
	TDot
	TMath
	TDoubleQuoted
)

// 配置tokenizer
parser := tokenizer.New()
parser.DefineTokens(TEquality, []string{"<", "<=", "==", ">=", ">", "!="})
parser.DefineTokens(TDot, []string{"."})
parser.DefineTokens(TMath, []string{"+", "-", "/", "*", "%"})
parser.DefineStringToken(TDoubleQuoted, `"`, `"`).SetEscapeSymbol(tokenizer.BackSlash)
parser.AllowKeywordSymbols(tokenizer.Underscore, tokenizer.Numbers)

// 创建标记流
stream := parser.ParseString(`user_id = 119 and modified > "2020-01-01 00:00:00" or amount >= 122.34`)
defer stream.Close()

// 遍历每个标记
for stream.IsValid() {
	if stream.CurrentToken().Is(tokenizer.TokenKeyword) {
		field := stream.CurrentToken().ValueString()
		// ...
	}
	stream.GoNext()
}

解析结果

string:  user_id  =  119  and  modified  >  "2020-01-01 00:00:00"  or  amount  >=  122.34
tokens: |user_id| =| 119| and| modified| >| "2020-01-01 00:00:00"| or| amount| >=| 122.34|
        |   0   | 1|  2 |  3 |    4    | 5|            6         | 7 |    8  | 9 |    10 |

0:  {key: TokenKeyword, value: "user_id"}                token.Value()          == "user_id"
1:  {key: TEquality, value: "="}                         token.Value()          == "="
2:  {key: TokenInteger, value: "119"}                    token.ValueInt64()     == 119
3:  {key: TokenKeyword, value: "and"}                    token.Value()          == "and"
4:  {key: TokenKeyword, value: "modified"}               token.Value()          == "modified"
5:  {key: TEquality, value: ">"}                         token.Value()          == ">"
6:  {key: TokenString, value: "\"2020-01-01 00:00:00\""} token.ValueUnescaped() == "2020-01-01 00:00:00"
7:  {key: TokenKeyword, value: "or"}                     token.Value()          == "and"
8:  {key: TokenKeyword, value: "amount"}                 token.Value()          == "amount"
9:  {key: TEquality, value: ">="}                        token.Value()          == ">="
10: {key: TokenFloat, value: "122.34"}                   token.ValueFloat64()   == 122.34

创建和解析

创建解析器

import "github.com/bzick/tokenizer"

var parser := tokenizer.New()
parser.AllowKeywordSymbols(tokenizer.Underscore, []rune{})
// ... 和其他配置代码

解析字符串或切片

有两种方式解析字符串或切片:

  • parser.ParseString(str)
  • parser.ParseBytes(slice)

解析无限流

fp, err := os.Open("data.json") // 大型JSON文件
// 检查文件系统,配置tokenizer...

stream := parser.ParseStream(fp, 4096).SetHistorySize(10)
defer stream.Close()
for stream.IsValid() {
	// ...
	stream.GoNext()
}

内置标记类型

  • tokenizer.TokenUnknown - 未指定的标记键
  • tokenizer.TokenKeyword - 关键字,任何字母组合,包括Unicode字母
  • tokenizer.TokenInteger - 整数值
  • tokenizer.TokenFloat - 浮点/双精度值
  • tokenizer.TokenString - 带引号的字符串
  • tokenizer.TokenStringFragment - 框架(带引号)字符串的片段

完整示例

JSON解析器示例

const (
	TokenCurlyOpen    = 1
	TokenCurlyClose   = 2
	TokenSquareOpen   = 3
	TokenSquareClose  = 4
	TokenColon        = 5
	TokenComma        = 6
	TokenDoubleQuoted = 7
)

// json解析器
parser := tokenizer.New()
parser.
	DefineTokens(TokenCurlyOpen, []string{"{"}).
	DefineTokens(TokenCurlyClose, []string{"}"}).
	DefineTokens(TokenSquareOpen, []string{"["}).
	DefineTokens(TokenSquareClose, []string{"]"}).
	DefineTokens(TokenColon, []string{":"}).
	DefineTokens(TokenComma, []string{","}).
	DefineStringToken(TokenDoubleQuoted, `"`, `"`).SetSpecialSymbols(tokenizer.DefaultStringEscapes)

stream := parser.ParseString(`{"key": [1]}`)

带注入的框架字符串

const (
	TokenOpenInjection = 1
	TokenCloseInjection = 2
	TokenQuotedString = 3
)

parser := tokenizer.New()
parser.DefineTokens(TokenOpenInjection, []string{"{{"})
parser.DefineTokens(TokenCloseInjection, []string{"}}"})
parser.DefineStringToken(TokenQuotedString, `"`, `"`).AddInjection(TokenOpenInjection, TokenCloseInjection)

parser.ParseString(`"one {{ two }} three"`)

性能基准

解析字符串/字节

pkg: tokenizer
cpu: Intel(R) Core(TM) i7-7820HQ CPU @ 2.90GHz
BenchmarkParseBytes
    stream_test.go:251: Speed: 70 bytes string with 19.689µs: 3555284 byte/sec
    stream_test.go:251: Speed: 7000 bytes string with 848.163µs: 8253130 byte/sec
    stream_test.go:251: Speed: 700000 bytes string with 75.685945ms: 9248744 byte/sec
    stream_test.go:251: Speed: 11093670 bytes string with 1.16611538s: 9513355 byte/sec
BenchmarkParseBytes-8   	  158481	      7358 ns/op

解析无限流

pkg: tokenizer
cpu: Intel(R) Core(TM) i7-7820HQ CPU @ 2.90GHz
BenchmarkParseInfStream
    stream_test.go:226: Speed: 70 bytes at 33.826µs: 2069414 byte/sec
    stream_test.go:226: Speed: 7000 bytes at 627.357µs: 11157921 byte/sec
    stream_test.go:226: Speed: 700000 bytes at 27.675799ms: 25292856 byte/sec
    stream_test.go:226: Speed: 30316440 bytes at 1.18061702s: 25678471 byte/sec
BenchmarkParseInfStream-8   	  433092	      2726 ns/op
PASS

已知问题

  • 零字节\x00 (\0)会停止解析

更多关于golang高效解析任意字符串、切片和无限缓冲区的分词插件库tokenizer的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang高效解析任意字符串、切片和无限缓冲区的分词插件库tokenizer的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


Golang高效分词插件库tokenizer使用指南

tokenizer是一个高效的Go语言分词库,支持任意字符串、切片和无限缓冲区的分词处理。下面我将详细介绍其使用方法并提供示例代码。

安装

go get github.com/sugarme/tokenizer

基本使用

1. 字符串分词

package main

import (
	"fmt"
	"github.com/sugarme/tokenizer"
)

func main() {
	// 创建分词器实例
	tk := tokenizer.NewTokenizer()

	// 简单字符串分词
	text := "Go语言高效分词库tokenizer"
	tokens := tk.Tokenize(text)
	
	fmt.Println("分词结果:")
	for _, token := range tokens {
		fmt.Printf("%s ", token)
	}
	// 输出: Go 语言 高效 分词 库 tokenizer
}

2. 切片分词

func sliceTokenization() {
	tk := tokenizer.NewTokenizer()
	
	// 字符串切片分词
	texts := []string{"Go语言", "高效分词", "库tokenizer"}
	
	fmt.Println("\n切片分词结果:")
	for _, text := range texts {
		tokens := tk.Tokenize(text)
		for _, token := range tokens {
			fmt.Printf("%s ", token)
		}
		fmt.Println()
	}
	/*
	输出:
	Go 语言 
	高效 分词 
	库 tokenizer 
	*/
}

高级功能

1. 自定义词典

func customDictionary() {
	tk := tokenizer.NewTokenizer()
	
	// 添加自定义词汇
	tk.AddWord("Go语言", 10) // 10是词频权重
	tk.AddWord("tokenizer", 10)
	
	text := "Go语言高效分词库tokenizer"
	tokens := tk.Tokenize(text)
	
	fmt.Println("\n自定义词典分词结果:")
	for _, token := range tokens {
		fmt.Printf("%s ", token)
	}
	// 输出: Go语言 高效 分词 库 tokenizer
}

2. 处理无限缓冲区

func infiniteBuffer() {
	tk := tokenizer.NewTokenizer()
	
	// 模拟无限数据流
	ch := make(chan string, 5)
	ch <- "第一部分数据"
	ch <- "第二部分数据"
	ch <- "第三部分数据"
	close(ch)
	
	fmt.Println("\n流式分词结果:")
	for text := range ch {
		tokens := tk.Tokenize(text)
		for _, token := range tokens {
			fmt.Printf("%s ", token)
		}
		fmt.Println()
	}
	/*
	输出:
	第一 部分 数据 
	第二 部分 数据 
	第三 部分 数据 
	*/
}

3. 性能优化配置

func performanceOptimized() {
	// 创建高性能分词器
	config := tokenizer.Config{
		NumThreads: 4,      // 使用4个线程
		BufferSize: 1024,   // 缓冲区大小
		DictPath:   "dict.txt", // 自定义词典路径
	}
	
	tk, err := tokenizer.NewTokenizerWithConfig(config)
	if err != nil {
		panic(err)
	}
	
	// 大批量数据处理
	largeText := make([]string, 1000)
	for i := range largeText {
		largeText[i] = fmt.Sprintf("文本数据%d", i)
	}
	
	results := make([][]string, len(largeText))
	for i, text := range largeText {
		results[i] = tk.Tokenize(text)
	}
	
	fmt.Println("\n性能优化分词示例完成")
}

实际应用示例

1. 搜索引擎分词

func searchEngineExample() {
	tk := tokenizer.NewTokenizer()
	
	query := "Go语言高性能网络编程"
	tokens := tk.Tokenize(query)
	
	fmt.Println("\n搜索查询分词:")
	for _, token := range tokens {
		fmt.Printf("%s ", token)
	}
	// 输出: Go 语言 高性能 网络 编程
}

2. 自然语言处理预处理

func nlpPreprocessing() {
	tk := tokenizer.NewTokenizer()
	
	// 添加NLP专用词汇
	tk.AddWord("BERT", 10)
	tk.AddWord("Transformer", 10)
	
	text := "使用BERT和Transformer模型进行自然语言处理"
	tokens := tk.Tokenize(text)
	
	fmt.Println("\nNLP预处理分词:")
	for _, token := range tokens {
		fmt.Printf("%s ", token)
	}
	// 输出: 使用 BERT 和 Transformer 模型 进行 自然 语言 处理
}

总结

tokenizer库提供了以下主要优势:

  1. 支持多种输入类型(字符串、切片、流)
  2. 高性能分词处理
  3. 支持自定义词典
  4. 可配置的并发处理
  5. 简单的API接口

通过合理配置和使用,tokenizer可以满足从简单文本处理到大规模数据流分词的各种需求。

回到顶部