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

[问题求助] chatgpt写的PowerShell正则平衡组示例改错

刚刚让chatgpt写几个平衡组示例, 但是执行结果都是错的, 求路过大佬改正
也第一次看到正则表达式可以多行表示, 而且行尾还能加注释, C#不能这样玩吧
  1. $pattern = @"
  2. \(
  3.     (?>                     # 开始一个平衡组
  4.         [^()]+              # 匹配除了括号以外的任意字符
  5.         |                   # 或者
  6.         (?<paren>\()        # 匹配左圆括号并将其压入名为paren的平衡组中
  7.         |                   # 或者
  8.         (?<-paren>\))       # 匹配右圆括号并将其弹出名为paren的平衡组中
  9.     )*                      # 重复上述步骤多次
  10.     (?(paren)(?!))          # 如果paren平衡组不为空,则匹配失败
  11. \)
  12. "@
  13. $text = "This is (a (test) string) with (nested (parentheses))."
  14. $matches = [regex]::Matches($text, $pattern)
  15. foreach ($match in $matches) {
  16.     Write-Host $match.Value
  17. }
复制代码

本帖最后由 WHY 于 2023-6-11 20:59 编辑

可能是我没有表达清楚什么意思,也可能是我高估了有些人的理解能力。

顶楼的正则,抛开所谓的"平衡组",可以这样写:
'\((?>[^()]+|\(|\))*\)'

如果取消固化分组,可以这样写:
'\(([^()]+|\(|\))*\)'

这与《精通正则表达式(第三版)》第225页的例子:"(\\.|[^"\\]+)*" 如出一辙。
第268页 "使用固化分组和占有优先量词" 已经把引起灾难性回溯的原因及解决办法说得很清楚了。

什么时候匹配失败会引起灾难性回溯?
比如:
  1. '(abcdefghijklmnopqrstuvwxyz' -match '\(([^()]+|\(|\))*\)'  
复制代码
当然,如果认为《精通正则表达式(第三版)》很烂,或者认为这本书已经过时,那我无话可说。

TOP

本帖最后由 xczxczxcz 于 2023-6-6 12:07 编辑

记得以前一直不知道正则到底是如何匹配,它每一步在做什么,因为不清不楚就不知道如何正确的写正则。然后,脑一热,准备写内存跟踪(因网上的教程不可靠,天下一大抄),架子都写了,然后就发现在一个网上的一个角落有位古董级大佬发有一篇日志,记录了他追踪内存的数据,他曾经也是不知正则的所以然就写了内存跟踪,看正则到底在内存中写了什么数据。然后的然后就再也不看网上的正则教程了,因为它妈的除了烂还是烂。现在就不知道发明正则的大佬的匹配和回溯过程是不是我们现在理解的一样。

* + 共同的东西是 遇到与条件相符,匹配立即停止,若匹配完,有结果,+ *都返回true; 没结果 * 返回
true; +返回false;  ?反向回溯,

因从没写过教程,感觉写的很乱,有些地方条件没写上有可能导致说法不成立;比如 [^\w]*, 这是不回溯的;但 [^\w]*a 这是回溯的
QQ: 己阵亡
脚本优先 [PowerShell win10]

TOP

回复 20# xczxczxcz


    好好看看"精通正则表达式第三版"第6章,第225页开始就是说的这个问题: "过渡回溯"。
.NET和其它如JAVA、PHP等等正则,都是基于传统NFA型的,我从来不认为这个很好,那个很垃圾。

TOP

([^()]+)*  和 [^()]+ 是两上不同的东西
QQ: 己阵亡
脚本优先 [PowerShell win10]

TOP

回复 19# WHY


    本来不想登陆的,但看了你写提示那个,感觉还是说两句的好。 请问您可以一个字符一个字符的 检索出 ([^()]+)* 的匹配和回溯教程吗? [^()]+ ,[^()]* 它们的的真正含意是什么吗? 还有你给的链接,那种破三烂的正则(看起来不像NET正则)就不要给链接(鄙视csdn,虽然俺开始也是看这的,但到后来发现里面的文章各种垃圾, 然后屏蔽),会降低您的智力。链接中的 (\.*)* 你想过这是什么破玩意吗。你可以想下这个回溯过程,指数级增长(还是那句话对正则回溯不清楚就不要写.* .+ .*? .+?之类), 还有 你确定 [^()]* [^()]+ 有回溯?可以自己实验下。不要拿网上那种垃圾文章还有阿三的微软例子来证明自己是对的。

  您应该知道 visual studio code 中最烂的应用是什么。 不夸张的说是powershell;vscode对py js java等支持的好得不得了,但对PS支持就是一个烂字。
QQ: 己阵亡
脚本优先 [PowerShell win10]

TOP

回复 9# xczxczxcz


    这里的“固化分组”并非多余,而是必须。
'([^()]+)*' 正则这样写,如果匹配失败,很容易引起 "灾难性回溯",或称 "无休止回溯"。

https://blog.csdn.net/weixin_40619578/article/details/127287867

TOP

本帖最后由 idwma 于 2023-4-12 13:45 编辑

回复 17# 小白龙

[ ]
不想问ai了搜一搜手册也是很好的方式呀
  1. https://learn.microsoft.com/zh-cn/dotnet/standard/base-types/regular-expression-options#ignore-white-space
复制代码

TOP

回复 15# idwma

大佬, 像这种能带注释的正则式有点实用, 以后想改的时候, 一目了然, 但是如果表达式中需要空格时怎么办? \s 虽然包含空格, 但还包含其它几个空字符

TOP

回复 15# idwma

多谢, 明白了

GPT的答案做个参考就行了, 关键还得自己要懂

TOP

回复 14# 小白龙

你看像这样,gpt给的没忽略非转义空白,加上(?x)就好了
  1. $pattern = @"
  2. (?x)\(
  3.     (?>                     # 开始一个平衡组
  4.         [^()]+              # 匹配除了括号以外的任意字符
  5.         |                   # 或者
  6.         (?<paren>\()        # 匹配左圆括号并将其压入名为paren的平衡组中
  7.         |                   # 或者
  8.         (?<-paren>\))       # 匹配右圆括号并将其弹出名为paren的平衡组中
  9.     )*                      # 重复上述步骤多次
  10.     (?(paren)(?!))          # 如果paren平衡组不为空,则匹配失败
  11. \)
  12. "@
复制代码

TOP

回复 13# idwma

什么意思, x大的那两个正则都可以直接出结果的, 在ps5.1

TOP

毕竟是人工智能嘛,还是离不开人,按x大的加上忽略转义空白(?x)其实也是有结果的

TOP

回复 10# xczxczxcz


    大佬, 牛X啊, 对正则理解太深刻了, 有什么精华的正则教程链接给推荐一下吗

TOP

回复 8# idwma


    哎, 问了七八轮了, 还没有答对, 太垃圾了

TOP

返回列表