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

[问题求助] [已解决]用正则表达式中的平衡组删除或修改特定字段

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

我要修改的多行字符串是一段C#代码, 里面{}环环相套! 可能必须要用平衡组了!

要点1: 类名和函数名后面的 { 的位置有如下两种情况
情况一 { 在新的行中
string FUN1()
{
}
情况二 { 在同一行的末尾
string FUN1() {
}

要点2: 函数的参数里可能有()嵌套()的情况
函数体里可能有{}嵌套{}的情况

要点3: 既要界定返回值类型的文本, 又要判断修饰词是否存在
感觉那三个需求, 用2个正则平衡式应该可以实现

下面代码的注释中有详细的描述, 请求路过大佬帮忙
情况1中的代码可以删除FUN1了, 但是因为没有使用平衡组, 如果{}互相嵌套就不灵了
  1. #--------------------------------------------------------------------情况1: 函数FUN1返回值类型void
  2. $s1 = @'
  3. using System;
  4. public class CLA
  5. {
  6. void FUN1()
  7. {
  8. Console.WriteLine("FUN1");
  9. }
  10. }
  11. '@
  12. $s1 -replace '(?s)void FUN1\(\).*?\}', ''
  13. #--------------------------------------------------------------------情况2: 返回值类型改为了 string
  14. $s2 = @'
  15. using System;
  16. public class CLA
  17. {
  18. string FUN1()
  19. {
  20. return "FUN1";
  21. }
  22. }
  23. '@
  24. #--------------------------------------------------------------------情况3: 加了修饰词 public
  25. $s3 = @'
  26. using System;
  27. public class CLA
  28. {
  29. public void FUN1()
  30. {
  31. Console.WriteLine("FUN1");
  32. }
  33. }
  34. '@
  35. #--------------------------------------------------------------------情况4: 加了修饰词 public static
  36. $s4 = @'
  37. using System;
  38. public class CLA
  39. {
  40. public static string FUN1()
  41. {
  42. return "FUN1";
  43. }
  44. }
  45. '@
  46. # 需求1 用1个正则表达式能删除指定函数名的函数, 要考虑函数名前的多种修饰词的情况
  47. #例如: 把上面四种情况中的 FUN1 函数删除掉
  48. # 需求2 用正则表达式: 修改指定函数名前的修饰词(不要修改返回值类型)
  49. #例如: 把 FUN1 函数的修饰词改为 public static (如果没有修饰词就加上,如果有就修改)
  50. # 需求3 用正则表达式: 修改指定类名前的修饰词
  51. #例如: 把 CLA 类的修饰词改为 private (如果没有修饰词就加上,如果有就修改)
复制代码
1

评分人数

    • Batcher: 感谢给帖子标题标注[已解决]字样PB + 2

本帖最后由 小白龙 于 2023-5-9 15:08 编辑

chatgpt的正则都太局限了也没用平衡组, 求路过大老出招, 优化改进一下!

-replace '(?s)(void|string)\s+FUN1\(\).*?\}', ''

-replace '(?<=\bstring)\s+(?=FUN1\(\))', 'public static'

-replace '(?<=class\s+)\w+', 'private'

TOP

多问几次试试

TOP

回复 3# idwma

多谢大佬, 这个正则只适用, void 前置关键字的情况, 还有其它几种

@"void\s+FUN1\s*\(\s*\)\s*\{(?:[^{}]+|\{(?<DEPTH>)|\}(?<-DEPTH>))*?(?(DEPTH)(?!))\}"

TOP

回复 3# idwma

替换成前置都能替换成功, 但是前置的关键词情况太多了, 怎样通用呢
  1. #--------------------------------------------------------------------情况1: 函数FUN1返回值类型void
  2. $s1 = @'
  3. using System;
  4. public class CLA
  5. {
  6. void FUN1()
  7. {
  8. Console.WriteLine("FUN1");
  9. }
  10. }
  11. '@
  12. #--------------------------------------------------------------------情况2: 返回值类型改为了 string
  13. $s2 = @'
  14. using System;
  15. public class CLA
  16. {
  17. string FUN1()
  18. {
  19. return "FUN1";
  20. }
  21. }
  22. '@
  23. #--------------------------------------------------------------------情况3: 加了修饰词 public
  24. $s3 = @'
  25. using System;
  26. public class CLA
  27. {
  28. public void FUN1()
  29. {
  30. Console.WriteLine("FUN1");
  31. }
  32. }
  33. '@
  34. #--------------------------------------------------------------------情况4: 加了修饰词 public static
  35. $s4 = @'
  36. using System;
  37. public class CLA
  38. {
  39. public static string FUN1()
  40. {
  41. return "FUN1";
  42. }
  43. }
  44. '@
  45. # 使用正则表达式删除指定函数
  46. $s1 -replace '(?s)void\s+FUN1\s*\(\s*\)\s*\{(?:[^{}]+|\{(?<DEPTH>)|\}(?<-DEPTH>))*?(?(DEPTH)(?!))\}'
  47. $s2 -replace '(?s)string\s+FUN1\s*\(\s*\)\s*\{(?:[^{}]+|\{(?<DEPTH>)|\}(?<-DEPTH>))*?(?(DEPTH)(?!))\}'
  48. $s3 -replace '(?s)public void\s+FUN1\s*\(\s*\)\s*\{(?:[^{}]+|\{(?<DEPTH>)|\}(?<-DEPTH>))*?(?(DEPTH)(?!))\}'
  49. $s4 -replace '(?s)public static string\s+FUN1\s*\(\s*\)\s*\{(?:[^{}]+|\{(?<DEPTH>)|\}(?<-DEPTH>))*?(?(DEPTH)(?!))\}'
复制代码

TOP

回复 4# 小白龙
  1. .*FUN1\s*\(\s*\)\s*\{(?:[^{}]+|\{(?<DEPTH>)|\}(?<-DEPTH>))*?(?(DEPTH)(?!))\}
复制代码

TOP

回复 6# idwma


    多谢大佬, 这个正则可以适应各种情况, 但是必须关闭单行模式才有效, 前面的正则式必须开单行, 为什么这么大差别呢?

TOP

回复 6# idwma


   下面两个需求, 怎样在上面正则的基础上修改? 搞不太懂, 问了几次chatgpt, 答非所问

# 需求2 用正则表达式: 修改指定函数名前的修饰词(不要修改返回值类型)
#例如: 把 FUN1 函数的修饰词改为 public static (如果没有修饰词就加上,如果有就修改)

# 需求3 用正则表达式: 修改指定类名前的修饰词
#例如: 把 CLA 类的修饰词改为 private (如果没有修饰词就加上,如果有就修改)

TOP

  1. $s1 -replace '.*(FUN1\s*\(\s*\)\s*\{(?:[^{}]+|\{(?<DEPTH>)|\}(?<-DEPTH>))*?(?(DEPTH)(?!))\})','public static $1'
  2. $s1 -replace '.*(CLA\s*\{(?:[^{}]+|\{(?<DEPTH>)|\}(?<-DEPTH>))*?(?(DEPTH)(?!))\})','private $1'
复制代码

TOP

回复 7# 小白龙


    不知道

TOP

本帖最后由 小白龙 于 2023-5-10 07:33 编辑

回复 9# idwma
  1. $s1 -replace '.*(FUN1\s*\(\s*\)\s*\{(?:[^{}]+|\{(?<DEPTH>)|\}(?<-DEPTH>))*?(?(DEPTH)(?!))\})','public static $1'
复制代码
用上面的正则会删除函数的返回值类型,  返回值类型也有很多种, 不固定, 下面示例中红色字是添加的修饰词, 其后蓝色字是返回值类型,不应修改
修改前
public class CLA
{
        void FUN1()
        {
                Console.WriteLine("FUN1");
        }
}
修改后
public class CLA
{
        public static void FUN1()
        {
                Console.WriteLine("FUN1");
        }
}

TOP

本帖最后由 小白龙 于 2023-5-10 07:53 编辑

回复 9# idwma


    返回值类型有下面几种, 都在函数名前, 除了第2个在括号中有空格之外, 其它的情况都是个整体, 内部没有空格, 这个好像有点难度了, 问gpt 完全不知道在说什么
int? GetNullableInt()
(string, int) GetPersonInfo()
IEnumerable<int> GetNumbers()
async Task<string> DownloadFileAsync(string url)
  1. // 返回Nullable类型
  2. int? GetNullableInt()
  3. {
  4.     int? result = null;
  5.     return result;
  6. }
  7. // 返回Tuple类型
  8. (string, int) GetPersonInfo()
  9. {
  10.     string name = "张三";
  11.     int age = 20;
  12.     return (name, age);
  13. }
  14. // 返回IEnumerable类型
  15. IEnumerable<int> GetNumbers()
  16. {
  17.     yield return 1;
  18.     yield return 2;
  19.     yield return 3;
  20. }
  21. // 返回Task类型
  22. async Task<string> DownloadFileAsync(string url)
  23. {
  24.     HttpClient client = new HttpClient();
  25.     HttpResponseMessage response = await client.GetAsync(url);
  26.     string content = await response.Content.ReadAsStringAsync();
  27.     return content;
  28. }
复制代码

TOP

本帖最后由 idwma 于 2023-5-10 11:33 编辑

回复 12# 小白龙

是这样吗
  1. $s1 -replace '(?<a>\s*)(private|public|static|async|(?<b>(string|void|int\?|\(string, int\)|IEnumerable<int>|Task<string>)\s*)|\s*)*(?<c>FUN1\s*\(\s*\)\s*\{(?:[^{}]+|\{(?<DEPTH>)|\}(?<-DEPTH>))*?(?(DEPTH)(?!))\})','${a}public static ${b}${c}'
复制代码
再试试这样
  1. $s1 -replace '(?<a>\s*)(private|public|static|async|(?<b>(\b\S+|\([^()]+\))\s*)|\s*)*(?<c>FUN1\s*\(\s*\)\s*\{(?:[^{}]+|\{(?<DEPTH>)|\}(?<-DEPTH>))*?(?(DEPTH)(?!))\})','${a}public static ${b}${c}'
复制代码

TOP

回复 13# idwma

多谢大佬, 这种具体限定几个关键字有个问题, 就是返回值类型还有很多, 例如  string[]
但是有个总规律:

函数名前都有一个空格

情况1. 空格前如果是个关括号 ) 则匹配的开括号( 这中间允许有空格, 像下面这样
(string, int) GetPersonInfo()

情况2.空格前都是连续的, 没有空格, 像#12楼的例子
就这两种情况

TOP

回复 14# 小白龙


    试试13楼的第二个,只用指定修饰符应该没多少个缺的自己加上去

TOP

返回列表