我有一个包含两个字符串之一的文件列表:
“ stuff
”或“ ;stuff
”
我正在尝试编写PowerShell脚本,该脚本将仅返回包含“ stuff
”的文件。下面的脚本当前返回 all 个文件,因为显然“ stuff
”是“ ;stuff
”的子字符串
对于我来说,我无法弄清楚如何仅匹配包含“ stuff
”的文件,而没有前面的;
Get-Content "C:\temp\list\list.txt" |
Where-Object { Select-String -Quiet -Pattern "stuff" -SimpleMatch $_ }
注意:C:\temp\list\list.txt
包含一个文件路径列表,每个文件路径都传递给Select-String
。
感谢您的帮助。
答案 0 :(得分:2)
您无法通过 literal 子字符串搜索(-SimpleMatch
)执行所需的匹配。
相反,使用带有负向后看断言 ((?<!..)
)的 regex 来排除{{1} }子字符串后跟一个stuff
字符:;
应用于您的命令:
(?<!;)stuff
正则表达式陷阱:
使用{strong>负(Get-Content "C:\temp\list\list.txt" |
Where-Object { Select-String -Quiet -Pattern '(?<!;)stuff' -LiteralPath $_ }
)字符集([^;]stuff
)来代替^
(请参阅{{3} });但是,如果[...]
出现在行的 处,这将不能正常工作,因为一个字符集(无论是否取反)都只匹配一个实际的字符,而不是行首的位置。
然后很容易将stuff
应用于否定字符集(对于可选匹配-0或1次出现):?
。但是,这将再次匹配包含[^;]?stuff
的字符串,因为;stuff
在技术上之前是取反字符集的“ 0重复出现”;因此,stuff
产生';stuff' -match '[^;]?stuff'
。
在这种情况下,只有后置断言可以正常工作-参见this answer。
答案 1 :(得分:1)
为补充@ mklement0的答案,我建议一种替代方法,使您的代码更易于阅读和理解:
MANIFEST.MF
这会将您的字符串变成对象(#requires -Version 4
@(Get-Content -Path 'C:\Temp\list\list.txt').
ForEach([IO.FileInfo]).
Where({ $PSItem | Select-String -Pattern '(?<!;)stuff' -Quiet })
),并利用数组函数ForEach
和Where
来简化/简洁。此外,这使您可以将System.IO.FilePath
参数将接受的路径作为对象传递到-Path
中,以使其更易于理解(我发现很长的参数集列表很困难阅读)。
答案 2 :(得分:-1)
发布的示例代码实际上不会运行,因为它将每行视为-Path
值。
您需要获取的内容,选择要查找的字符串,然后使用Where-Object
过滤结果
Get-Content "C:\temp\list\list.txt" | Select-String -Pattern "stuff" | Where-Object {$_ -notmatch ";stuff"}
如果需要,您可以创建更复杂的正则表达式,但取决于文件中结果数据的样子