|
|
搞完野路子了,看看有没有正道。相信这种问题肯定有成熟的模块,AI 推的第一个模块:
Text::Balanced - Extract delimited text sequences from strings.
先看第一个极简示例
- use Text::Balanced qw(extract_bracketed);
- my $text = "(inside(lv2:(lv3:deep)))right";
- my ($extracted, $remainder) = extract_bracketed($text, '()');
- printf "%s\n", $extracted;
- printf "%s\n", $remainder;
复制代码
结果
- (inside(lv2:(lv3:deep)))
- right
复制代码
这个extract_bracketed 只负责提取从(括号起到右侧配对的)括号范围的内容,它不会返回带层次的结构体。
如果左侧带有其他字符例如 "abc(括号内的)..." 那么需要手动去掉左侧内容或者提取从左括号( 开始的子串交给 extract_bracketed 处理
接着让ai写了一个递归的版本,像剥洋葱一样处理
- #!/usr/bin/env perl
- use strict;
- use warnings;
- use Text::Balanced qw(extract_bracketed);
- my $text = "left (inside(lv2:(lv3:deep))) def(inside2(lv2:(lv3:deep1)(lv3:deep2))) right";
- print "orig: $text\n";
- print "-" x 50 . "\n";
- # 第一步:处理顶层的所有独立括号组
- # 因为字符串开头可能不是括号,或者中间有 "def" 隔开,我们需要循环查找
- process_level($text, 0);
- sub process_level
- {
- my ($str, $level) = @_;
-
- # 缩进显示
- my $indent = " " x $level;
-
- # 只要字符串里还有左括号,就继续尝试提取
- while ($str =~ /\(/)
- {
- # 找到第一个左括号的位置,截取子串供 extract_bracketed 使用
- # 因为 extract_bracketed 必须从字符串开头就是括号才能工作
- my $start_pos = index($str, '(');
- my $substring = substr($str, $start_pos);
-
- # 执行提取
- my ($extracted, $remainder) = extract_bracketed($substring, '()');
-
- if (defined $extracted)
- {
- # 1. 打印当前层级的完整括号内容
- print "${indent}Lv$level: $extracted\n";
-
- # 2. 准备下一层级的数据:去掉最外层的括号
- # 提取的内容格式是 "(...)", 我们取中间部分 [1 .. length-2]
- my $inner_content = substr($extracted, 1, -1);
-
- # 3. 递归处理内部内容(进入下一层)
- process_level($inner_content, $level + 1);
-
- # 4. 更新 $str,跳过刚才处理过的这部分,继续寻找同级的下一个括号
- # 原字符串 = (括号前的垃圾) + (提取的部分) + (剩余部分)
- # 我们需要保留:(括号前的垃圾) + (extract_bracketed 返回的 remainder)
- # 注意:$substring 是从 $start_pos 开始的,所以 $start_pos 之前的部分要拼回去
- my $prefix = substr($str, 0, $start_pos);
- $str = $prefix . $remainder;
-
- }
- else
- {
- # 理论上如果 =~ /\(/ 成立,extract_bracketed 应该能提取到,除非括号不匹配
- warn "检测到左括号但无法提取完整结构,可能存在语法错误。\n";
- last;
- }
- }
- }
复制代码
打印结果
- orig: left (inside(lv2:(lv3:deep))) def(inside2(lv2:(lv3:deep1)(lv3:deep2))) right
- --------------------------------------------------
- Lv0: (inside(lv2:(lv3:deep)))
- Lv1: (lv2:(lv3:deep))
- Lv2: (lv3:deep)
- Lv0: (inside2(lv2:(lv3:deep1)(lv3:deep2)))
- Lv1: (lv2:(lv3:deep1)(lv3:deep2))
- Lv2: (lv3:deep1)
- Lv2: (lv3:deep2)
复制代码
耗时 200 ms |
|