Regex for multiple non-consecutive backslash for each line not working - regex

I'm trying to list all the files that contain multiple non-consecutive backslashes in each line.
Here's my script in powershell
Get-ChildItem -Path "D:\config_files" -Include "*.xml","*.txt" -Recurse |
Foreach-Object{
$file = $_.FullName
(Get-Content $file) |
Where-Object{
$_ -match '^(.*)=(")(.*?[^\\])(\\.*)(")(.*)$'
} |
Select-Object -Unique |
ForEach-Object{
Write-Host "$file : $_"
$_ | Out-File -FilePath 'matches.txt' -Append
}
}
Here's my regex
^(.*)=(")(.*?[^\\])(\\.*)(")(.*)$
These are the expected conditions.
starts with characters
followed by ="
contains non-consecutive backslash
followed by "
End with any characters
The regex should detect the text below
<add key="12345 value="\\machine\001\0z991\master" />
<settings file="..\app\service\config\settings.config">
<key="config" value="..\app\bin\config"/>
The problem is it only works in a single line. I already added '$' end the line

Related

replace a string with a regex in multiple files

I have more than 10000 text files that I want to replace the string searchResult with a regex in that specific text file using Notepad++ or PowerShell. For example here is one of the text files:
searchresult : [{"name": myRegexMatch .....}
After substitution:
myRegexMatch : [{"name": myRegexMatch .....}
The regex match is different in every file. I just want to replace searchResult in every single file with the regex in that file.
This should kind of get you started
$regex = '(?<=searchresult\s:\s\[{"name":\s).*(?=})'
Get-ChildItem $pathToFiles -Recurse | Where-Object { -not $_.PSIsContainer } |
ForEach-Object {
$text = (Get-Content $_ -Raw)
$value = [regex]::Match($text, $regex).Groups[1].Value
$text -replace "searchresult",$value | Set-Content -path $_
}

PowerShell - How to Update a file based on content from another file

I've searched all over including here at StackOverFlow and I cannot seem to find the solution I am needing help with. Here is my issue.
Lets say in File1.txt I have the following (no spaces between each line)
\\Serv02\LOC6\Client\726C30\032383\2200018023.pdf
\\Serv02\LOC6\Client\726C30\032383\2200718091.pdf
\\Serv02\LOC6\Client\726C30\030684\2300309040.pdf
\\Serv02\LOC6\Client\726C30\031274\2300429971.pdf
File2.txt will have the same information, however, I am needing to add a 1 right before the .pdf for each one (within file2.txt)
Example:
\\Serv02\LOC6\Client\726C30\032383\22000180231.pdf
I can easily update file2.txt using a RegEx statement, however it's only updating the contents based on that RegEx statement.
File2.txt will have a lot more data in it than file1.txt (more of the exact type of information). I am only needing to update file2.txt adding in the 1 right before .pdf BASED on what is in file1.txt
Here is the code I am using but as you can see it does not read file1.txt at all, I'm just using a RegEx statement to update file2.txt adding in the 1 before .pdf (the code below works to add in the 1 before .pdf, but I'm not iterating through file1.txt)
clear-host
set-location c:\temp
$File = "C:\Temp\file1.txt"
$FileZ = "C:\Temp\file2.txt"
$File2 = (Get-ChildItem $fileZ) | Select -ExpandProperty BaseName
$regex01 = '(\\Serv02\LOC6\Client\726C30\\d{1,6}\\d{1,10})(.pdf)$'
get-content $fileZ | % { $_ -replace $regex01, '${1}1${2}' -join "`r`n" } | out-file -Encoding default "c:\Temp\$File2.txt"
start-sleep -Seconds 2
$NewMRC = Get-ChildItem "$file2.txt" | Select -ExpandProperty Name
Get-ChildItem $NewMRC | rename-item -NewName {$_.Name -replace ".txt",".MRC2"}
If file1.txt had another line that didn't match up to the RegEx as shown above, file2.txt would not be updated with that line
\\Serv03\LOC7\Client\780D30\031456\8675309123.pdf
I hope I have explained this well enough. I'm not new to PowerShell but I am far from an expert. Any assistance is greatly appreciated.
I've modified your code as follows. The approach is read the content of File1.txt and store it in a variable. Then iterate on each line of File2.txt to check it against the regex as well as if that line is present in file1 content. If yes then replace it with whatever you want. Output this to a .tmp file in append mode. Once all the lines in File2.txt are processed, then replace it with .tmp file.
clear-host
set-location c:\temp
$File = "file1.txt"
$FileZ = "file2.txt"
# PS2
$File1 = get-content $File | Out-String
# PS3
# $File1 = get-content $File -Raw
$File2 = (Get-ChildItem $fileZ) | Select -ExpandProperty BaseName
if( test-path "$File2.tmp" ) { remove-item "$File2.tmp" }
$regex01 = '(\\\\Serv02\\LOC6\\Client\\726C30\\\d{1,6}\\\d{1,10})(.pdf)$'
get-content $fileZ |% {
$line = $_
$find = $line -replace '\\','\\'
if ( ($line -match $regex01) -AND ( $File1 -match $find ) ) {
$line -replace $regex01,'${1}1${2}' -join "`r`n"
} else {
$line
}
} | out-file "$File2.tmp" -append
remove-item "$File2.txt"
rename-item "$File2.tmp" "$File2.txt"
#start-sleep -Seconds 2
#$NewMRC = Get-ChildItem "$file2.txt" | Select -ExpandProperty Name
#Get-ChildItem $NewMRC | rename-item -NewName {$_.Name -replace ".txt",".MRC2"}
Notes:
The last 3 lines of your code doesn't seem to be related to your problem statement. So I've commented those lines.
$find = $line -replace '\\','\\': We are replacing single backslash \ with double backslash \\. But in the first parameter to -replace it must be escaped and in second param it must NOT be. So, even though they look same, they are interpreted differently.
One way to do this: Retrieve file content of first file into an array, then retrieve content of second file. For each line in second file: If first file's content has a line matching the current line, output modified line; otherwise, just output the current line.
$pattern = '(\\{2}(?:[^\\]+\\)+)([^\\\.]+)(\.pdf)'
$file1Content = Get-Content "file1.txt"
Get-Content "file2.txt" | ForEach-Object {
if ( $file1Content -contains $_ ) {
$_ | Select-String $pattern | ForEach-Object {
"{0}{1}1{2}" -f
$_.Matches[0].Groups[1].Value,
$_.Matches[0].Groups[2].Value,
$_.Matches[0].Groups[3].Value
}
}
else {
$_
}
}
First match group ($_.Matches[0].Groups[1].Value) is \\servername\sharename\path, second match group is filename without extension, and third match group is the file extension.

Powershell regex to remove comma but not delimiter

I'm bringing a delimited CSV into PowerShell to remove line feeds with the code below which works but I've found I need to remove extra commas as well but not sure how to format the regex.
(Get-Content -Path $fullpath -Raw) -replace '(?<!\x0d)\x0a'," " | out-file $fullpath
My input CSV is:
"field1","field2","field3","fred,mary,john,brian","field5"
So I want to keep "," (including the quotes), but remove any other commas on their own.
So I'd end up with:
"field1","field2","field3","fred mary john brian","field5"
This will do it.
(Get-Content -Path $fullpath -Raw) -replace '(?<!"),|,(?!")',' ' | out-file $fullpath
It will only match the comma's that are either not proceeded by a quote or not followed by it.
Which is true for all commas except those surrounded by quotes: ","
To only remove the commas of a specific field, you could use Import-Csv with a Header.
$csvin = Import-Csv -Path $fullpath -Header f1,f2,f3,f4,f5
$csvin |%{$_.f4=$_.f4.replace(',',' ')}
$csvin |ConvertTo-Csv -NoTypeInformation |Select-Object -Skip 1 |Set-Content -Path $fullpath
You can import the CSV file, remove commas from all fields, and write it as CSV again. No need for trying to write a regex that keeps the structure intact:
$data = Import-Csv foo.csv
$columns = $data | gm | where MemberType -eq NoteProperty | % Name
$newdata = $data | %{
foreach ($c in $columns) {
$_.$c = $_.$c -replace ',',' '
}
}
$newdata | Export-Csv foo-rewritten.csv

remove lines which start with *(asterik) in powershell select-string output

I am working on a code so that it find lines which has $control but should remove lines which start with * at first column
I am working with following but doesn't seem to work ..
$result = Get-Content $file.fullName | Select-String $control | Select-String -pattern "\^*" -notmatch
Thanks in advance
You're escaping the wrong character. You do not want to escape ^ as that's your anchor for "starting with". You'll want to escape the asterix, so try this:
$result = Get-Content $file.fullName | Select-String $control | select-string -pattern "^\*" -notmatch
Also, if all you want is the lines, you could also use this:
Get-Content $file.fullName | ? { $_ -match $control -and $_ -notmatch '^\*'}

Powershell regex group replacing

I want to replace some text in every script file in folder, and I'm trying to use this PS code:
$pattern = '(FROM [a-zA-Z0-9_.]{1,100})(?<replacement_place>[a-zA-Z0-9_.]{1,7})'
Get-ChildItem -Path 'D:\Scripts' -Recurse -Include *.sql | ForEach-Object { (Get-Content $_.fullname) -replace $pattern, 'replace text' | Set-Content $_.fullname }
But I have no idea how to keep first part of expression, and just replace the second one. Any idea how can I do this? Thanks.
Not sure that provided regex for tables names is correct, but anyway you could replace with captures using variables $1, $2 and so on, and following syntax: 'Doe, John' -ireplace '(\w+), (\w+)', '$2 $1'
Note that the replacement pattern either needs to be in single quotes ('') or have the $ signs of the replacement group specifiers escaped ("`$2 `$1").
# may better replace with $pattern = '(FROM) (?<replacement_place>[a-zA-Z0-9_.]{1,7})'
$pattern = '(FROM [a-zA-Z0-9_.]{1,100})(?<replacement_place>[a-zA-Z0-9_.]{1,7})'
Get-ChildItem -Path 'D:\Scripts' -Recurse -Include *.sql | % `
{
(Get-Content $_.fullname) | % `
{ $_-replace $pattern, '$1 replace text' } |
Set-Content $_.fullname -Force
}
If you need to reference other variables in your replacement expression (as you may), you can use a double-quoted string and escape the capture dollars with a backtick
{ $_-replace $pattern, "`$1 replacement text with $somePoshVariable" } |