You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何对Supply或其他类流序列执行正则表达式匹配?

实现流文本的跨块正则匹配

在Raku中,你完全可以实现流文本的跨块正则匹配,无需将全部文本读入内存。核心是维持匹配状态,以下是两种常用方案:

方案1:手动维护残留缓冲区

适合简单正则,手动管理未完成匹配的前缀:

# 初始化缓冲区和目标正则
my $remainder = '';
my $target-regex = /foo \d+/; # 替换为你的正则

# 处理Supply流(Channel/IO::Handle同理,先转为Supply)
$your-supply.tap(-> $chunk {
    $remainder ~= $chunk;
    # 全局扫描匹配,直到无法找到更多匹配
    while $remainder ~~ m:g/$target-regex/ {
        say "匹配到: $/"; # 这里处理匹配结果
        # 更新缓冲区为当前匹配结束后的剩余文本
        $remainder = $remainder.substr($/.pos + $/.chars);
    }
    # 可选:优化缓冲区大小(避免无限增长)
    # 对于固定结构的正则,可保留最长可能的未完成前缀长度
    # 比如正则是/aaa/,最多保留2个字符,超过则截断
    # $remainder = $remainder.substr(*-2) if $remainder.chars > 2;
});

原理:每次将新文本块拼接到残留缓冲区,扫描所有完整匹配后,保留缓冲区中未完成匹配的部分(比如fo可能和下一个块的o123组成foo123)。

方案2:使用Grammar增量解析

适合复杂正则/语法规则,Raku的Grammar原生支持增量解析,通过Cursor维持状态:

# 定义匹配规则的Grammar
grammar StreamParser {
    token TOP { <match>+ }
    token match { foo \d+ } # 替换为你的匹配规则
}

# 定义匹配后的处理逻辑
class MatchActions {
    method match($/) {
        say "匹配结果: $/"; # 处理匹配到的内容
    }
}

# 初始化解析游标
my $cursor = StreamParser.parse('', :actions(MatchActions));

# 处理流中的每个文本块
$your-supply.tap(-> $chunk {
    $cursor = $cursor.continue($chunk);
});

原理:Cursor对象会记录当前解析的状态,每次调用continue($chunk)时,会在原有状态基础上继续解析新文本块,匹配到规则时自动触发Actions中的处理方法。

适配不同流源

  • IO::Handle:通过.Supply方法转为流:$handle.Supply.tap(...)
  • Channel:通过.Supply方法转为流,或直接循环读取:loop { my $chunk = $channel.receive; ... }

内容的提问来源于stack exchange,提问作者Owen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 00:24:17