首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >Powershell regex失败并出现意外结果

Powershell regex失败并出现意外结果
EN

Stack Overflow用户
提问于 2022-06-24 13:21:36
回答 3查看 70关注 0票数 1

如果某个单词在块中的任何地方存在,我将试图隔离一组行。

例如,我有以下文本。

代码语言:javascript
代码运行次数:0
运行
复制
A1: blah blah
B1: blah blah foobar

A2: foobar blah blah
B2: blah blah foobar
C2: blah blah
D2: blah blah

A3: blah blah
B3: blah blah
C3: blah blah

块可以包含任意数量的行,用空行分隔,而我要查找的单词foobar可以在块中的任何位置--这是唯一的常量,起始数字列表(A1、B1等)是为了简单起见,这些更改完全是为了简单。

这就是我能想到的准则。显然,这不符合块线大小的动态性质。但至少这起作用是应该的。

代码语言:javascript
代码运行次数:0
运行
复制
.*[\r\n]+.*(foobar).*[\r\n]+(.*[\n\r]){1}

Result:
A1: blah blah
B1: blah blah foobar

A2: foobar blah blah
B2: blah blah foobar
C2: blah blah

我进一步完善了正则表达式,并提出了以下内容:

代码语言:javascript
代码运行次数:0
运行
复制
(.\n?)*(foobar).*(\n?.)*

Result:
A1: blah blah
B1: blah blah foobar

A2: foobar blah blah
B2: blah blah foobar
C2: blah blah
D2: blah blah

这正是我所需要的,并且在我尝试过的每一个在线regex测试站点上都做得很好。但是一旦我把这个放到Powershell中,代码就会吐出所有的东西,没有过滤任何东西。

下面是我正在使用的代码:

代码语言:javascript
代码运行次数:0
运行
复制
$regex = '(.\n?)*(foobar).*(\n?.)*'

$response = Invoke-RestMethod $url
$response | Select-String $regex -AllMatches | ForEach-Object {
    foreach($foorbar in $_.matches.Value) {
        $foobar | Out-File $fileOutput -Append
    }
} 

URL包含这些数据块的网页,而不是其他数据块。对于新的正则表达式,没有任何解析,但是旧的正则表达式按照它的假设工作。所以我假设这是正则表达式出了问题。

如果有人能指出这里有什么不对,非常感谢!

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2022-06-24 18:36:41

你的判断力

代码语言:javascript
代码运行次数:0
运行
复制
$regex = '(.\n?)*(foobar).*(\n?.)*'

如果存在回车字符,则(\n?.)*可以跨空行匹配,因为.将与之匹配。(Windows使用CRLF行尾。)

由于同样的原因,Wiktor的regex (以(?:\n.+)*结尾)也将不适用于CRLF线尾。

相反,您可以使用,例如

代码语言:javascript
代码运行次数:0
运行
复制
$regex = '(?:[^\r\n]+\r?\n)*?.*foobar.*(?:\r?\n[^\r\n]+)*'

通过使用[^\r\n]而不是.来匹配不是回车或换行符(linefeed)的行中的至少一个字符,从而避免了这个问题。

票数 1
EN

Stack Overflow用户

发布于 2022-06-24 15:14:25

您可以使用

代码语言:javascript
代码运行次数:0
运行
复制
$regex = '(?m)^(?:.+\n)*?.*foobar.*(?:\n.+)*'

regex演示。详细信息

  • (?m) -a RegexOptions.Multiline选项
  • ^ -任何行的开始
  • (?:.+\n)*? -任何零或更多(但尽可能少)非空行
  • .*foobar.* -一个包含foobar的行
  • (?:\n.+)* -零或更多(尽可能多)非空行。

在PowerShell中,您还可以使用

代码语言:javascript
代码运行次数:0
运行
复制
$regex = '(?m)^(?:.+\n)*?.*foobar.*(?:\n.+)*'

$response = Invoke-RestMethod $url
($response | Select-String -Pattern $regex -AllMatches | %{ $_.Matches.Value }) -join "`r`n`r`n" >> $fileOutput
票数 1
EN

Stack Overflow用户

发布于 2022-06-24 16:42:37

首先拆分输入文本可以简化解决方案:

代码语言:javascript
代码运行次数:0
运行
复制
$lf = [Environment]::NewLine
$response -split '\r?\n\r?\n' -match 'foobar' -join "$lf$lf" >>$fileOutput
  • $response -split '\r?\n\r?\n'将文本拆分为双新行(空行)。模式\r?\n与单一的新行相匹配,既适用于\r\n,也适用于Unix \n风格。结果是一个文本块数组,删除了两个新行。
  • -match 'foobar'过滤文本块的数组,导致只包含“foobar”的这些块。注意,根据-match操作数是单个字符串还是字符串数组,LHS运算符的工作方式不同。对于单个字符串,结果将是一个boolean,它指示模式是否匹配。
  • 使用-join "$lf$lf",我们再次将匹配的文本块连接到一个字符串中,以产生所需的输出。
  • 最后,重定向操作符>>将字符串附加到输出文件(您也可以使用| Out-File -Append )。
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72744752

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档