选择字符串:仅当字符串前面没有特定字符时才匹配字符串



我有一个包含两个字符串之一的文件列表:

"stuff"或";stuff">

我正在尝试编写一个PowerShell脚本,该脚本将仅返回包含"stuff"的文件。下面的脚本目前返回所有文件,因为显然"stuff"是";stuff"的子字符串

。对于我的一生,我无法弄清楚如何只匹配包含"stuff"的文件,而没有前面的;

Get-Content "C:templistlist.txt" |
Where-Object { Select-String -Quiet -Pattern "stuff" -SimpleMatch $_ }

注意:C:templistlist.txt包含每个文件路径传递给Select-String的文件路径列表。

感谢您的帮助。

您无法使用文本子字符串搜索 (-SimpleMatch) 执行所需的匹配。

相反,使用带有否定后视断言((?<!..)) 的正则表达式排除前面有;字符的stuff子字符串:(?<!;)stuff

应用于您的命令:

Get-Content "C:templistlist.txt" | 
Where-Object { Select-String -Quiet -Pattern '(?<!;)stuff' -LiteralPath $_ }

正则表达式陷阱:

使用
  • 否定(^)字符集([...])是很诱人的[^;]stuff(见此答案);但是,如果stuff出现在一行的最开头,这将不能按预期工作,因为字符集 - 无论是否否定 - 仅匹配实际字符,而不是行首位置

  • 然后,很容易将?应用于否定的字符集(对于可选匹配 - 出现 0 或 1):[^;]?stuff。但是,这将再次匹配包含;stuff的字符串,因为stuff在技术上前面是否定字符集的"0 重复出现";因此,';stuff' -match '[^;]?stuff'产生$true

在这种情况下,只有后视断言才能正常工作 - 请参阅 regular-expressions.info。

为了补充@mklement0的答案,我建议使用另一种方法来使您的代码更易于阅读和理解:

#requires -Version 4
@(Get-Content -Path 'C:Templistlist.txt').
ForEach([IO.FileInfo]).
Where({ $PSItem | Select-String -Pattern '(?<!;)stuff' -Quiet })

这会将您的字符串转换为对象(System.IO.FilePath),并利用数组函数ForEachWhere来简洁。 此外,这允许您将路径作为对象通过管道传输,这些对象将被-Path参数接受到Select-String中,以使其更易于理解(我发现长长的参数集列表难以阅读)。

发布的示例代码实际上不会运行,因为它会将每一行视为-Path值。

您需要的是获取内容,选择所需的字符串,然后使用Where-Object筛选结果

Get-Content "C:templistlist.txt" | Select-String -Pattern "stuff" | Where-Object {$_ -notmatch ";stuff"}

如果需要,您可以创建一个更复杂的正则表达式,但这取决于文件中的结果数据的外观

相关内容

  • 没有找到相关文章

最新更新