I have a list of keywords (sometimes with non-alphanumeric characters) that I’d like to find in a list of files. I can do that with the code below, but I want to avoid matching keywords if they are found inside another word, e.g.:
Keywords.csv:
Keywords
Lo.rem <-- Match if not prefixed by nor suffixed with a letter
is <-- Same
simply) <-- Match if not prefixed by a letter
printing. <-- Same
(text <-- Match if not suffixed with a letter
-and <-- Same
Files.csv:
Files
C:\AFolder\aFile.txt
C:\AFolder\AnotherFolder\anotherFile.txt
C:\AFolder\anotherFile2.txt
Here's my code so far if useful:
$keywords = (((Import-Csv "C:\Keywords.csv" | Where Keywords).Keywords)-replace '[[ *?()\\.]','\$&') #Import list of keywords to search for
$paths = ((Import-Csv "C:\Files.csv" | Where Files).Files) #Import list of files to look for matching keywords
$count = 0
ForEach ($path in $paths) {
$file = [System.IO.FileInfo]$path
Add-Content -Path "C:\Matches\$($count)__$($file.BaseName)_Matches.txt" -Value $file.FullName #Create a file in C:\Matches and insert the path of the file being searched
$hash = @{}
Get-Content $file |
Select-String -Pattern $keywords -AllMatches |
Foreach {$_.Matches.Value} |
%{if($hash.$_ -eq $null) { $_ }; $hash.$_ = 1} | #I don't remember what this does, probably fixes error messages I was getting
Out-File -FilePath "C:\Matches\$($count)__$($file.BaseName)_Matches.txt" -Append -Encoding UTF8 #Appends keywords that were found to the file created
$count = $count 1
}
I’ve tried playing with regex negative lookahead/lookbehind but did not get anywhere, especially since I’m a beginner in PowerShell, e.g.:
Select-String -Pattern "(?<![A-Za-z])$($keywords)(?![A-Za-z])" -AllMatches
Any suggestions? Much appreciated
CodePudding user response:
This will escape any regex reserved characters in your keyword list, and join them with |
to specify the OR condition, and then wrap them in parenthesis.
"(?<![A-Za-z])($(($keywords|%{[regex]::escape($_)}) -join '|'))(?![A-Za-z])"
That would be consumed as something like this:
"(?<![A-Za-z])(Lo\.rem|is|simply\)|printing\.|\(text|-and)(?![A-Za-z])"