找回密码
 注册
搜索
[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
楼主: 小白龙

[问题求助] PowerShell怎样用正则匹配成对的括号?

[复制链接]
 楼主| 发表于 2023-3-12 21:55:09 | 显示全部楼层
回复 15# idwma

虽然看不懂, 但还是非常感谢!

难道我的问题, 用正则, WHY大佬的思路是唯一正解了吗?  不能在went大佬的正则基础上改改吗?
发表于 2023-3-12 22:51:20 | 显示全部楼层
本帖最后由 WHY 于 2023-3-13 23:40 编辑

  1. Function Get-BalanceSet([ref]$str){
  2.     $index = $str.Value.IndexOf('abc(');

  3.     if ($index -lt 0){         #不含 'abc(' 子串,退出函数
  4.         return;
  5.     }

  6.     $str.Value = $str.Value.SubString($index);   #删掉 'abc(' 之前的所有字符
  7.     $arr = [Collections.ArrayList]@();
  8.   
  9.     $n = 0;
  10.     $m = 0;

  11.     for ($i=0; $i -lt $str.Value.Length; $i++){  #遍历字符串每个字符
  12.         $s1 = $str.Value.SubString($i, 1);       #截取第i个字符,赋值给$s1
  13.         [void]$arr.Add($s1);                     #再将$s1存放到数组
  14.         if ( $s1 -eq ')' ){                      #右括弧,n减1
  15.             $n--;
  16.         } elseIf ( $s1 -eq '(' ){                #左括弧,n加1
  17.             $n++;
  18.             $m++;
  19.         }
  20.         if ($n -eq 0 -and $m -gt 0){             #若n=0且左括弧数不为0
  21.             [void]$out.Add($arr -join '');       #匹配结果存放到$out
  22.             break;                               #退出For
  23.         }
  24.     }
  25.     $str.Value = $str.Value.SubString(4);        #删除开头的 'abc(' 4个字符
  26.     Get-BalanceSet ([ref]$str.Value);            #递归
  27. }

  28. $s = 'xzc abc(s "(abc)"); dfg(); abc(123(ggg))';

  29. $out = [Collections.ArrayList]@();               #数组,存放结果
  30. Get-BalanceSet ([ref]$s);
  31. $out;

  32. echo 'Done';
  33. [Console]::ReadLine();
复制代码

评分

参与人数 2技术 +2 收起 理由
523066680 + 1 乐于助人
小白龙 + 1 乐于助人

查看全部评分

 楼主| 发表于 2023-3-13 10:38:06 | 显示全部楼层
回复 17# WHY


    多谢大佬, 太细心了, 感谢
发表于 2023-3-13 17:43:53 | 显示全部楼层
说一下吧,正则匹配只有3种情况:
0次(包括多次0次)
最少次
最多次

字符串'xzc abc(s "(abc)"); dfg()' 中的 'abc(' 可以通过最少次1次匹配得到
但是与 'abc(' 中的左括号匹配的右括号是不属于上面三种情况
0次就是匹配不到
最少次会匹配到 'abc)'中的右括号
最多次会匹配到 'dfg()' 中的右括号
指定次数虽然可能匹配得到,但是不通用,除非所有需要匹配的都是所指定的次数

平衡组是在正则引擎的支持上实现这种不属于三种情况匹配的通用解决方案之一
平衡组其实就是命名组的自动计数,匹配到左括号就计数加1,匹配到右括号就计数减1,最后判断计数是否为0(或偶数)来判断是否匹配

也可以手动根据平衡组的实现来手动匹配,例如

  1. $s='xzc abc(s "(abc)"); dfg()'
  2. $ss=[regex]::Match($s, 'abc\(.+\)').value
  3. $a=[Collections.ArrayList]::new()
  4. $a.Add(-1)
  5. (0..($ss.Length-1)).ForEach({
  6. if($ss[$_] -eq '('){$a.Add($_)}
  7. if($ss[$_] -eq ')'){
  8.     $a.Removeat($a.Count-1)
  9.     if($a.Count -eq 1){$a[0]=$_;break}
  10. }
  11. })
  12. [Console]::WriteLine($ss.Substring(0,$a[0]+1))
复制代码

评分

参与人数 1技术 +1 收起 理由
小白龙 + 1 乐于助人

查看全部评分

发表于 2023-3-13 18:41:55 | 显示全部楼层
只能搞简单的匹配 复杂的不能
  1. $s='xzc abc(s "(abc)"); dfg()'
  2. [regex]::Match($s, '(abc\([^\)\(]*)(\(.*\))*([^\)\(]*\))').Value;
复制代码

评分

参与人数 1技术 +1 收起 理由
小白龙 + 1 乐于助人

查看全部评分

 楼主| 发表于 2023-3-13 20:05:46 | 显示全部楼层
本帖最后由 小白龙 于 2023-3-13 20:07 编辑

回复 20# terse


    大佬实在是高, 这个正则兼容性不错, 不支持平衡组的软件也能用, 目前还没遇到匹配不到的

难道还有匹配不了的情况吗? 能说说吗? 怕到时候掉坑里
发表于 2023-3-13 20:45:48 | 显示全部楼层
回复 21# 小白龙
当出现如下的情况,便匹配不能,要修改这样
当然还会出现其他状况 所以不通用
  1. $s = 'xzc abc(s "(abc)");a, d(fg())'
  2. [regex]::Match($s, '(abc\([^\)\(]*)(\(.*?\))*([^\)\(]*\))').Value;
复制代码
 楼主| 发表于 2023-3-13 20:50:47 | 显示全部楼层
回复 22# terse


    哦, 看来WHY大佬的平衡组正则式, 确实是唯一正解了, 能适应各种情况
发表于 2023-3-13 22:24:43 | 显示全部楼层
多研究一下正则 这东西烧脑
您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|手机版|小黑屋|批处理之家 ( 渝ICP备10000708号 )

GMT+8, 2026-3-17 06:27 , Processed in 0.030578 second(s), 13 queries , File On.

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表