[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
返回列表 发帖

[问题求助] powershell按先后顺序成对匹配花括号

本帖最后由 小白龙 于 2024-1-22 17:40 编辑

又一个平衡组难题, gpt也没搞定, 是我描述的不够清楚吗? 求路过大佬支招
下面注释中有详细描述
  1. cls
  2. <#
  3. 用powershell代码加1条正则来判断某多行文本末尾的3个关花括号 } 是否分别,成对地匹配前面的 namespace xxx, public class xxx,  public xxx 后的开括号 {
  4. 1.如果有三个匹配, 就输出: 三个匹配
  5. 2.如果有两个匹配, 就输出: 两个匹配
  6. 3.如果有一个匹配, 就输出: 一个匹配
  7. 4.如果无一个匹配, 就输出: 无匹配
  8. 注意:
  9. 1.末尾有几个括号就匹配对应的几层, 层要按上面的先后顺序
  10. 2.开花括号 { 有时没有占独一行,而是在其上一行的末尾, 例如: $s2 和 $s3
  11. 3.开花括号 { 前的xxx 表示不确定的文本, xxx前面的文本则是严格匹配的文本
  12. #>
  13. $s1 = @'
  14. using System;
  15. namespace _1
  16. {
  17. public class _2
  18. {
  19. public static void Main()
  20. {
  21. string s1 = "中";
  22. string s2 = "国";
  23. }
  24. }
  25. }
  26. '@
  27. #输出 => 三个匹配
  28. $s2 = @'
  29. using System;
  30. public class _2 {
  31. public static void Main() {
  32. string s1 = "中";
  33. string s2 = "国";
  34. }
  35. }
  36. '@
  37. #输出 => 两个匹配
  38. $s3 = @'
  39. using System;
  40. public static void Main(){
  41. string s1 = "中";
  42. string s2 = "国";
  43. }
  44. '@
  45. #输出 => 一个匹配
  46. $s4 = @'
  47. using System;
  48. string s1 = "中";
  49. string s2 = "国";
  50. '@
  51. #输出 => 无匹配
复制代码

如果是下面那样的话输出结果是啥???
  1. $ss = @'
  2. using System;
  3. public static void Main(){
  4. //}}}}}}}{{{{{{{{
  5. string s1 = "中{{{{{{{{{{{";
  6. string s2 = "国}}}}}}}";
  7. }
  8. //}}}}}}}
  9. '@
复制代码

TOP

回复 2# Five66


       这情况应该极少遇到

TOP

下面是gpt的回答, 没匹配出三个, 另外也太复杂了, 有没有可能一行正则就搞定了?
  1. function CountBraces
  2. {
  3. param (
  4. [string]$inputText
  5. )
  6. # 匹配 namespace xxx, public class xxx, public xxx 后的开括号 {
  7. $regex = '(?<=namespace|public\sclass|public)(?:.*{)'
  8. # 提取匹配的部分
  9. $matches = [regex]::Matches($inputText, $regex)
  10. # 计算匹配的层级数
  11. $braceCounts = $matches | ForEach-Object {
  12. $braceCount = 0
  13. $charArray = $_.Value.ToCharArray()
  14. # 逐字符检查层级
  15. foreach ($char in $charArray)
  16. {
  17. if ($char -eq '{')
  18. {
  19. $braceCount++
  20. }
  21. elseif ($char -eq '}')
  22. {
  23. $braceCount--
  24. }
  25. }
  26. $braceCount
  27. }
  28. # 统计不同层级的次数
  29. $result = $braceCounts | Group-Object | ForEach-Object {
  30. "$($_.Count)个匹配"
  31. }
  32. # 输出结果
  33. $result -join ", "
  34. }
  35. # 测试样例
  36. $testCases = @(
  37. $s1,
  38. $s2,
  39. $s3,
  40. $s4
  41. )
  42. $testCases | ForEach-Object {
  43. CountBraces $_
  44. Write-Host '---'
  45. }
复制代码

TOP

把之前的改改
  1. $p = "(?=((?:namespace|public)[^{]+\{(?:[^{}]+|(?<Open>)\{|(?<-Open>)\})*(?(Open)(?!))\}))"
  2. [Regex]::Matches($s, $p).count + '个'
复制代码

TOP

回复 5# idwma

多谢大佬, 提示类型错误, 改为下面就可以了
[Regex]::Matches($s1, $p).count.ToString() + '个'


有两个问题, 我看正则中有(?:namespace|public) 这里只有第一层和第三层的, 第二层的public class没有, 如果实际例子中变成了public kkkkk也会被匹配上了, 如果加上去, 这些会按层次先后去匹配吗?

还有难题, 就缺哪层时就补哪层怎么解决呢?
例如, 有两层, 缺第一层, 就在两层外补上namespace A {  ........  }
例如, 有一层, 缺前两层, 就在该层外补上namespace A {   public class B {  ........  }   }
例如, 三层全缺, 就在外补上namespace A{   public class B { public static void Main() {  ........  }  }   }

TOP

回复 5# idwma


    我看到过哪个正则的文章中有写到, 能把匹配的值填充到 <变量名> 中, 之后就可以使用这个变量, 用这个方法感觉解决我楼上的补层的问题很不错, 但是不懂怎么操作

TOP

回复 6# 小白龙


    看不懂,不会了
状态就像先这样,再这样,然后这样。

TOP

返回列表