Board logo

标题: [问题求助] PowerShell正则平衡组获取{}内多行文本 [打印本页]

作者: 小白龙    时间: 2023-5-26 17:06     标题: PowerShell正则平衡组获取{}内多行文本

下面要处理的字符串变量$s 内有两个类,分别是 xx类 和 zz类, 每个类下都有 Main函数 和 hello函数
我想获取所有Main函数体的文本,下面的代码执行后, 始终只能取两行, gpt也被我搞晕了, 几十回合都在重复一个代码,  哎

在下对平衡组还是一知半解, 求路过大佬帮助
最好能写成一个函数, 函数名 getFuncText 有两个参数, 第1个函数是函数名, 第二个函数是 类名

用法1: 如果只有第1个参数 函数名 没有第2个参数 类名 那就把下面所有类中的 该函数内的文本全输出
getFuncText "Main"

用法2: 如果既有第1个参数 函数名 又有第2个参数 类名 那就只把该类下的 该函数内的文本输出
getFuncText "Main" "xx"

感觉描述是很清楚的, GPT确理解不了, 可能太难了

另外, 类前面的修饰符会有多种情况: 下面是idwma大佬写的平衡组表达示, 供参考:
$s -match '(?<a>\n\s*)(private|public|static|async|(?<b>(\b\S+|\([^()]+\))\s*))*(?<c>class\s+cs\s*(\([^)]*\))*\s*\{(?:[^{}]+|\{(?<DEPTH>)|\}(?<-DEPTH>))*?(?(DEPTH)(?!))\})'
$regex='(?<a>\n\s*)(private|public|static|async|(?<b>(\b\S+|\([^()]+\))\s*))*(?<c>(abc|cd)\s*\([^)]*\)\s*\{(?:[^{}]+|\{(?<DEPTH>)|\}(?<-DEPTH>))*?(?(DEPTH)(?!))\})'
  1. $s = @'
  2. using System;
  3. public class xx
  4. {
  5. public static void Main()
  6. {
  7. string s = "xzc abc(s \"(abc)\")); dfg()";
  8. string p = @"}";
  9. string q = @"}{{";
  10. string[] result = matches(s, p);
  11. }
  12. public static string hello(string s, string p)
  13. {
  14. Match match = Regex.Match(s, p);
  15. string fullMatch = match.Value;
  16. }
  17. }
  18. public class zz
  19. {
  20. public static void Main()
  21. {
  22. string s = "xzc abc(s \"(abc)\")); dfg()";
  23. string p = @"}";
  24. string q = @"{{}";
  25. string[] result = matches(s, p);
  26. }
  27. public static string hello(string s, string p)
  28. {
  29. Match match = Regex.Match(s, p);
  30. string fullMatch = match.Value;
  31. }
  32. }
  33. '@
  34. $regex = '(?<=Main\s*\(\)\s*\{)(?<BODY>(?:[^{}]+|(?<OPEN>\{)|(?<-OPEN>\}))*)(?(OPEN)(?!))(?=\})'
  35. if ($s -match $regex)
  36. {
  37. $match = $Matches['BODY']
  38. Write-Output $match
  39. }
复制代码

作者: idwma    时间: 2023-5-26 18:46

本帖最后由 idwma 于 2023-5-26 18:55 编辑
  1. function getFuncText($a,$b){
  2. if(!$b){$b='\S+'}
  3. $r='(?<a>\n\s*)(private|public|static|async|(?<b>(\b\S+|\([^()]+\))\s*))*(?<c>'+$b+'\s*(\([^)]*\))*\s*\{\n(?>(?<d>\s*(private|public|static|async|(?<b>(\b\S+|\([^()]+\))\s*))*(?<c>'+$a+'\s*(\([^)]*\))*\s*\{(?>[^{}\/\x22\x27]+|\/\/[^\n]+|/\*(\n|.)*?\*/|[\x22][^\x22]*[\x22]|[\x27][^\x27]*[\x27]|[^{}]|\{(?<DEPTH>)|\}(?<-DEPTH>))*?(?(DEPTH)(?!))\}))|[^{}\/\x22\x27]+|\/\/[^\n]+|/\*(\n|.)*?\*/|[\x22\x27](\n|.)*?[\x22\x27]|[^{}]|\{(?<DEPTH>)|\}(?<-DEPTH>))*?(?(DEPTH)(?!))\})'
  4. [regex]::Matches($s, $r).groups|?{$_.name -eq 'd'}|%{$_.captures.value}
  5. }
复制代码

作者: 小白龙    时间: 2023-5-26 18:58

回复 2# idwma


    多谢大佬, 试了一下, 没有输出
  1. $s = @'
  2. using System;
  3. public class xx
  4. {
  5. public static void Main()
  6. {
  7. string s = "xzc abc(s \"(abc)\")); dfg()";
  8. string p = @"}";
  9. string q = @"}{{";
  10. string[] result = matches(s, p);
  11. }
  12. public static string hello(string s, string p)
  13. {
  14. Match match = Regex.Match(s, p);
  15. string fullMatch = match.Value;
  16. }
  17. }
  18. public class zz
  19. {
  20. public static void Main()
  21. {
  22. string s = "xzc abc(s \"(abc)\")); dfg()";
  23. string p = @"}";
  24. string q = @"{{}";
  25. string[] result = matches(s, p);
  26. }
  27. public static string hello(string s, string p)
  28. {
  29. Match match = Regex.Match(s, p);
  30. string fullMatch = match.Value;
  31. }
  32. }
  33. '@
  34. function getFuncText($a, $b)
  35. {
  36. if (!$b) { $b = '\S+' }
  37. $r = '(?<a>\n\s*)(private|public|static|async|(?<b>(\b\S+|\([^()]+\))\s*))*(?<c>' + $b + '\s*(\([^)]*\))*\s*\{(?>(?<d>(\n\s*)(private|public|static|async|(?<b>(\b\S+|\([^()]+\))\s*))*(?<c>' + $a + '\s*(\([^)]*\))*\s*\{(?>[^{}\/\x22\x27]+|\/\/[^\n]+|/\*(\n|.)*?\*/|[\x22][^\x22]*[\x22]|[\x27][^\x27]*[\x27]|[^{}]|\{(?<DEPTH>)|\}(?<-DEPTH>))*?(?(DEPTH)(?!))\}))|[^{}\/\x22\x27]+|\/\/[^\n]+|/\*(\n|.)*?\*/|[\x22\x27](\n|.)*?[\x22\x27]|[^{}]|\{(?<DEPTH>)|\}(?<-DEPTH>))*?(?(DEPTH)(?!))\})'
  38. [regex]::Matches($s, $r).groups | ?{ $_.name -eq 'd' } | %{ $_.captures.value }
  39. }
  40. getFuncText  -a "Main"
  41. "--------------------------"
  42. getFuncText -a "Main" -b "zz"
复制代码

作者: idwma    时间: 2023-5-26 19:04

回复 3# 小白龙


    测过是有的

作者: 小白龙    时间: 2023-5-26 19:09

回复 4# idwma


    我的没有任何输出, window7 x64 powershll 5.1
作者: idwma    时间: 2023-5-26 19:34

回复 5# 小白龙


    用win7 5.1测了也是有的

作者: 小白龙    时间: 2023-5-26 20:03

回复 6# idwma

这是我测试的文件
    https://t.wss.ink/f/bax41qzzn9f 复制链接到浏览器打开
作者: 小白龙    时间: 2023-5-26 20:50

回复 6# idwma

奇怪, 在另一台电脑上也不行,
作者: idwma    时间: 2023-5-26 21:06

  1. function getFuncText($a, $b)
  2. {
  3. if (!$b) { $b = '\S+' }
  4. $r = '(?<a>\r?\n\s*)(private|public|static|async|(?<b>(\b\S+|\([^()]+\))\s*))*(?<c>' + $b + '\s*(\([^)]*\))*\s*\{(?>(?<d>(\r?\n\s*)(private|public|static|async|(?<b>(\b\S+|\([^()]+\))\s*))*(?<c>' + $a + '\s*(\([^)]*\))*\s*\{(?>[^{}\/\x22\x27]+|\/\/[^\n]+|/\*(\r?\n|.)*?\*/|[\x22][^\x22]*[\x22]|[\x27][^\x27]*[\x27]|[^{}]|\{(?<DEPTH>)|\}(?<-DEPTH>))*?(?(DEPTH)(?!))\}))|[^{}\/\x22\x27]+|\/\/[^\n]+|/\*(\r?\n|.)*?\*/|[\x22\x27](\r?\n|.)*?[\x22\x27]|[^{}]|\{(?<DEPTH>)|\}(?<-DEPTH>))*?(?(DEPTH)(?!))\})'
  5. [regex]::Matches($s, $r).groups | ?{ $_.name -eq 'd' } | %{ $_.captures.value }
  6. }
复制代码

作者: 小白龙    时间: 2023-5-26 21:15

回复 9# idwma
现在输出如下, 但是我只需要红色字部分
        public static void Main()
        {
                string s = "xzc abc(s \"(abc)\")); dfg()";
                string p = @"}";
                string q = @"}{{";
                string[] result = matches(s, p);

        }

        public static void Main()
        {
                string s = "xzc abc(s \"(abc)\")); dfg()";
                string p = @"}";
                string q = @"{{}";
                string[] result = matches(s, p);

        }
--------------------------

        public static void Main()
        {
                string s = "xzc abc(s \"(abc)\")); dfg()";
                string p = @"}";
                string q = @"{{}";
                string[] result = matches(s, p);

        }
  1. $s = @'
  2. using System;
  3. public class xx
  4. {
  5. public static void Main()
  6. {
  7. string s = "xzc abc(s \"(abc)\")); dfg()";
  8. string p = @"}";
  9. string q = @"}{{";
  10. string[] result = matches(s, p);
  11. }
  12. public static string hello(string s, string p)
  13. {
  14. Match match = Regex.Match(s, p);
  15. string fullMatch = match.Value;
  16. }
  17. }
  18. public class zz
  19. {
  20. public static void Main()
  21. {
  22. string s = "xzc abc(s \"(abc)\")); dfg()";
  23. string p = @"}";
  24. string q = @"{{}";
  25. string[] result = matches(s, p);
  26. }
  27. public static string hello(string s, string p)
  28. {
  29. Match match = Regex.Match(s, p);
  30. string fullMatch = match.Value;
  31. }
  32. }
  33. '@
  34. function getFuncText($a, $b)
  35. {
  36. if (!$b) { $b = '\S+' }
  37. $r = '(?<a>\r?\n\s*)(private|public|static|async|(?<b>(\b\S+|\([^()]+\))\s*))*(?<c>' + $b + '\s*(\([^)]*\))*\s*\{(?>(?<d>(\r?\n\s*)(private|public|static|async|(?<b>(\b\S+|\([^()]+\))\s*))*(?<c>' + $a + '\s*(\([^)]*\))*\s*\{(?>[^{}\/\x22\x27]+|\/\/[^\n]+|/\*(\r?\n|.)*?\*/|[\x22][^\x22]*[\x22]|[\x27][^\x27]*[\x27]|[^{}]|\{(?<DEPTH>)|\}(?<-DEPTH>))*?(?(DEPTH)(?!))\}))|[^{}\/\x22\x27]+|\/\/[^\n]+|/\*(\r?\n|.)*?\*/|[\x22\x27](\r?\n|.)*?[\x22\x27]|[^{}]|\{(?<DEPTH>)|\}(?<-DEPTH>))*?(?(DEPTH)(?!))\})'
  38. [regex]::Matches($s, $r).groups | ?{ $_.name -eq 'd' } | %{ $_.captures.value }
  39. }
  40. getFuncText  -a "Main"
  41. "--------------------------"
  42. getFuncText -a "Main" -b "zz"
复制代码

作者: idwma    时间: 2023-5-26 21:48

回复 10# 小白龙
  1. function getFuncText($a, $b)
  2. {
  3. if (!$b) { $b = '\S+' }
  4. $r = '(?<a>\r?\n\s*)(private|public|static|async|(?<b>(\b\S+|\([^()]+\))\s*))*(?<c>' + $b + '\s*(\([^)]*\))*\s*\{(?>((\r?\n\s*)(private|public|static|async|(?<b>(\b\S+|\([^()]+\))\s*))*(?<c>' + $a + '\s*(\([^)]*\))*\s*\{\s*(?<d>(?>[^{}\/\x22\x27]+|\/\/[^\n]+|/\*(\r?\n|.)*?\*/|[\x22][^\x22]*[\x22]|[\x27][^\x27]*[\x27]|[^{}]|\{(?<DEPTH>)|\}(?<-DEPTH>))*?(?(DEPTH)(?!)))\}))|[^{}\/\x22\x27]+|\/\/[^\n]+|/\*(\r?\n|.)*?\*/|[\x22\x27](\r?\n|.)*?[\x22\x27]|[^{}]|\{(?<DEPTH>)|\}(?<-DEPTH>))*?(?(DEPTH)(?!))\})'
  5. [regex]::Matches($s, $r).groups | ?{ $_.name -eq 'd' } | %{ $_.captures.value }
  6. }
复制代码

作者: 小白龙    时间: 2023-5-26 22:15

本帖最后由 小白龙 于 2023-5-26 22:16 编辑

回复 11# idwma

多谢大佬, 请问, 现在写的正则这么复杂, 能适应 函数体{}花括号内的所有情况吗?
换句话说, 能取到{}内各种情况下的文本了吧
作者: idwma    时间: 2023-5-26 22:16

回复 12# 小白龙


    不太清楚碰上了再改
作者: 小白龙    时间: 2023-5-26 22:29

回复 13# idwma

我让GPT优化精简正则, 怎么改都是错的, 正则太长了, 如果有更可靠, 更简洁的方法就好了
作者: idwma    时间: 2023-5-27 09:25

回复 14# 小白龙
  1. function getFuncText($a, $b)
  2. {
  3. if (!$b) { $b = '\S+' }
  4. $c='private|public|static'
  5. $d='[^{}\/\x22\x27\r\n]+|\/\/[^\r\n]+|/\*.*?\*/|[\x22][^\x22]*[\x22]|[\x27][^\x27]*[\x27]|[^{}]|\{(?<DEPTH>)|\}(?<-DEPTH>))*?(?(DEPTH)(?!))'
  6. $r = '(?s)('+$c+'|\s+)*class\s+'+$b+'\s*\{(?>('+$c+'|void|\s+)*'+$a+'\s*(\([^)]*\))*\s*\{\s*(?<d>(?>'+$d+')\}|'+$d+'\}'
  7. [regex]::Matches($s, $r).groups | ?{ $_.name -eq 'd' } | %{ $_.captures.value }
  8. }
复制代码

作者: idwma    时间: 2023-5-27 15:06

本帖最后由 idwma 于 2023-5-27 15:07 编辑

还可以试试这个
  1. function getFuncText($a, $b)
  2. {
  3. if (!$b) { $b = '\S+' }
  4. $r = '(?s)public\sclass\s'+$b+'\s*\{.+?(private|public|static|void|\s+)*'+$a+'\s*(\([^)]*\))*\s*\{\s*(?<d>(?>[^{}\/\x22\x27\r\n]+|\/\/[^\r\n]+|/\*.*?\*/|[\x22][^\x22]*[\x22]|[\x27][^\x27]*[\x27]|\r?\n|\{(?<DEPTH>)|\}(?<-DEPTH>))*?(?(DEPTH)(?!)))\}'
  5. [regex]::Matches($s, $r).groups | ?{ $_.name -eq 'd' } | %{ $_.captures.value }
  6. }
复制代码

作者: 小白龙    时间: 2023-5-27 17:58

回复 16# idwma
多谢大佬, 可以正确输出, 和前面那个原理一样吗? 只是精简了一下吗
作者: 小白龙    时间: 2023-5-27 18:02

本帖最后由 小白龙 于 2023-5-27 18:04 编辑

回复 16# idwma

$s = gc -Path "$HOME\Desktop\abc.txt"

用gc获取文件中的字符串, 多行的结果不正确 ,并在一行了, 把字符串写在代码中没事
  1. $s = @'
  2. using System;
  3. public class xx
  4. {
  5. public static void Main()
  6. {
  7. string s = "xzc abc(s \"(abc)\")); dfg()";
  8. string s = "xzc abc(s \"(abc)\")); dfg()";
  9. string p = @"}";
  10. string p = @"}";
  11. string p = @"}";
  12. string s = "xzc abc(s \"(abc)\")); dfg()";
  13. }
  14. public static string hello(string s, string p)
  15. {
  16. string fullMatch = match.Value;
  17. }
  18. }
  19. public class zz
  20. {
  21. public static void Main()
  22. {
  23. string s = "xzc abc(s \"(abc)\")); dfg()";
  24. string p = @"}";
  25. }
  26. public static string hello(string s, string p)
  27. {
  28. string fullMatch = match.Value;
  29. }
  30. }
  31. '@
复制代码

作者: idwma    时间: 2023-5-27 20:10

回复 17# 小白龙
是什么地方不懂
回复 18# 小白龙
gc得到的是数组,要转成字符
作者: 小白龙    时间: 2023-5-27 20:37

回复 19# idwma

多谢提醒, 加了一个-raw就可以了
作者: 小白龙    时间: 2023-5-27 21:02

回复 19# idwma

大佬, 新的这个正则的执行速度比前面的那个要快多了




欢迎光临 批处理之家 (http://www.bathome.net/) Powered by Discuz! 7.2