regex `>'是'〈='的快捷方式吗?

aor9mmx1  于 2023-02-25  发布在  其他
关注(0)|答案(1)|浏览(357)

通过一些复杂的测试,我最终可能发现了一条捷径。
PowerShell中的lookbehind应该使用<=语法,当在PowerShell中搜索lookbehind时,该语法在其他多个地方被引用,例如this Microsoft blog
以这个简单的例子Regex:
(?〉^[^x]*)$

  • )开始向后看
  • ^[^x]* 测试字符 * x * 是否从字符串开头开始就不存在
  • )关闭后视
  • $固定行的结尾

当我测试它时:

'sample = x' -match '(?>^[^x]*)$'
False
'sample = ' -match '(?>^[^x]*)$'
True

第一个块返回false:lookbehind不匹配没有 * x * 的字符串。
第二个块返回true:lookbehind匹配没有 * x * 的字符串。
好像管用了!
现在,如果我尝试使用<=语法:
一个二个一个一个
它有相同的行为。
这是PowerShell中RegEx查找的"捷径"吗?或者>为什么能工作?

435|PS(7.2.1) C:\Users\User\Documents [230211-15:03:27]> $PSVersionTable

Name                           Value
----                           -----
PSVersion                      7.2.1
PSEdition                      Core
GitCommitId                    7.2.1
OS                             Microsoft Windows 10.0.22621
Platform                       Win32NT
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0…}
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
WSManStackVersion              3.0
unhi4e5o

unhi4e5o1#

    • TL;医生**
  • 正则表达式分组构造(?<=…)(?>…)用于不同的目的,只是在您的特定场景中 * 碰巧 * 工作相同;在您的方案中不需要 * 两者都不需要 *。
  • 使用'...' -notmatch 'x'测试给定字符串是否包含'x'的任何示例(如果 * 不是 *,则返回$true)。
    • 背景资料**:

您引用的两个分组构造用于不同的目的(包含的子表达式用下面的占位符表示):

  • (?<=…)是一个(零宽度,正)后看Assert:
  • 它是一个 * 非捕获 * 分组构造,必须在其余表达式匹配的地方 * 之前 *(左边,即"向后看")匹配封闭的子表达式,而不捕获子表达式匹配的内容。
  • 从本质上讲,这意味着:当这个构造后面的内容匹配时,还要确保(Assert)它前面的内容匹配(?<=…)内部的子表达式;如果不匹配,则没有总体匹配;如果是,则不 * 捕获 *(包括在结果中)其匹配。
  • 因此,该构造只有在置于 * 捕获 * 构造之前时才有意义;例如:
# Matches only 'unheard of', because only in it is the match
# for 'hear.' preceded by 'un'
# Captures only 'heard' from the matching string, not the 'un'
'heard from', 'unheard of' -match '(?<=un)hear.'
  • (?>…)是一个原子组,也称为 * 非回溯子表达式 *:
  • 它是一个 * 捕获 * 分组构造-类似于一个常规捕获组(匹配子表达式)(…)-* 除了 * 它 * 从不回溯 *。
  • 从本质上讲,这意味着:一旦子表达式找到了匹配项,就不允许基于表达式的剩余部分进行回溯;当已知回溯不会成功时,该构造主要用作 * 性能优化 *。
# Atomic group:
# -> $false, because the atomic group fully consumes the string,
#    so there's nothing for '.' to match *after* the group.
'abc!' -match '(?>.+).'

# Regular capture group:
# -> $true, with backtracking; the capture group captures 'abc'
'abc!' -match '(.+).'
    • 你尝试了什么**:

(?<=^[^x]*)$-带有 * lookbehindAssert * 的正则表达式
如上所述,没有理由在使用lookbehind * assertion * 之后不使用 * capturing * 表达式,因为根据定义,您的正则表达式不会捕获任何内容($本身就是一个 * assertion *)。
因为你要匹配 * 整个字符串 immediate * 的简化方式是根本不使用分组构造(但是请看下面的部分):
^[^x]*$
作为一种优化,如果您明确希望阻止默认情况下发生的捕获,请使用非捕获组(?:…)
(?:^[^x]*$)
(?>^[^x]*)$-带有 * 原子组 * 的正则表达式
由于您要匹配的是 * whole string *,所以没有理由使用 * atomic * 组,因为不需要防止回溯,所以这个正则表达式实际上与(^[^x]*)$相同,即常规捕获组(后面跟着$)。
如前所述,没有理由在这里"捕获"任何内容,因此(?:^[^x]*$)将防止这种情况。
简而言之:

  • 两个正则表达式都完全匹配输入字符串 *,因此不需要分组构造(除非显式地阻止捕获)。
  • 请继续阅读,寻找一个简单得多的解决方案。
    • 后退一步**

概念上最简单且最有效的解决方案是:

'...' -notmatch 'x'

也就是说,您可以让-notmatch(PowerShell的-match运算符的求反形式)查找(最多一个)x,并对布尔结果求反,以便 * not * 查找任何x返回$true
换句话说:如果输入字符串中存在 * no * x,则测试成功。

相关问题