Failing to get Substring from Path in PowerShell - powershell

There are these two given paths
$x = 'C:\temp\folder1\data'
$t = 'C:\temp\'
Desired is to get '\folder1\data' to a new variable
I tried
Select-String -Path $x -Pattern $t
which ended in
Select-String: The string C:\temp\ is not a valid regular expression: Invalid pattern 'C:\temp\' at offset 8. Illegal \\ at end of pattern.
Also I tried to replace the backslash with a pipe symbol which ended in
Select-String: Cannot find path 'C:\|temp|folder1|data' because it does not exist.
This
$x -replace $t,""
does bring back
||folder1|data
Which is close.
How would I correctly extract a search string from a path string ins PS ?

You need to escape the string before you can use it as a regex pattern:
PS ~> $x -replace [regex]::Escape($t)
folder1\data
Trim $t before escaping if you don't want to remove the trailing slash:
PS ~> $x -replace [regex]::Escape($t.TrimEnd('\'))
\folder1\data
To ensure the replacement only occurs at the start of the string, add a caret ^, which in regex is a metacharacter designating the "start of string":
$x -replace "^$([regex]::Escape($t.TrimEnd('\')))"

Related

Replace whole string if part of the string is "not correct"

i need to make a script for "check/replace/add string to the file.
The "correct" string is "google.com 44.10.15.9" I have a part of the script for adding the whole line, but i don't know how to make it check other options, If the string would be there but only "google.com" without address or with wrong address.
My work looks like this.
$file= 'C:\Users\fialbvoj\Desktop\testPS.txt'
$name=" google.com "
$IP=" 44.10.15.9 "
$line="google.com 44.10.15.9"
$search=(Get-Content $file | Select-String -Pattern 'google.com 44.10.15.9').Matches.Success
if ($search ) {"Success"
} else {
Add-Content -Path $file -Value $line
}
Thank you in advance.
Best Regards
Select-String accepts regular expressions for the -Pattern parameter which allows you to use a regular expression for the IPAddress instead of a literal IP address, e.g.:
... |Select-String 'google\.com ((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)\.?\b){4}'
To replace the any pattern with the "correct string" (aka IP address):
(Get-Content $file) -Replace 'google\.com ((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)\.?\b){4}', 'google.com 44.10.15.9' |Set-Content $file
Note 1: the parenthesis around (Get-Content $file) are only required if you need to write back to the same file.
Note 2: the backslash in google\.com is required to escape the dot which normally represents any character in a regular expression.

Split string in Powershell

I have sth written in a ".ini" file that i want to read from PS. The file gives the value "notepad.exe" and i want to give the value "notepad" into a variable. So i do the following:
$CLREXE = Get-Content -Path "T:\keeran\Test-kill\test.ini" | Select-String -Pattern 'CLREXE'
#split the value from "CLREXE ="
$CLREXE = $CLREXE -split "="
#everything fine untill here
$CLREXE = $CLREXE[1]
#i am trying to omit ".exe" here. But it doesn't work
$d = $CLREXE -split "." | Select-String -NotMatch 'exe'
How can i do this ?
#Mathias R. Jessen is already answered your question.
But instead of splitting on filename you could use the GetFileNameWithoutExtension method from .NET Path class.
$CLREXE = "notepad.exe"
$fileNameWithoutExtension = [System.IO.Path]::GetFileNameWithoutExtension($CLREXE)
Write-Host $fileNameWithoutExtension # this will print just 'notepad'
-split is a regex operator, and . is a special metacharacter in regex - so you need to escape it:
$CLREXE -split '\.'
A better way would be to use the -replace operator to remove the last . and everything after it:
$CLREXE -replace '\.[^\.]+$'
The regex pattern matches one literal dot (\.), then 1 or more non-dots ([^\.]+) followed by the end of the string $.
If you're not comfortable with regular expressions, you can also use .NET's native string methods for this:
$CLREXE.Remove($CLREXE.LastIndexOf('.'))
Here, we use String.LastIndexOf to locate the index (the position in the string) of the last occurrence of ., then removing anything from there on out

Powershell script help needed - Find word beginning with something and replace it

I'm trying to change a string within a file to a string with timestamp on the end but cant work out how to find the initial string using a regex in Powershell
(Get-Content sw.js).replace('SW-cache-v.*', 'SW-cache-v'+$(Get-Date -format "s")) | Set-Content sw.js
the SW-cache-v.* isn't working for me, I'm just not picking up the string in order to replace it.
Any thoughts on how to do it?
In PowerShell, the -replace comparison operator uses regex matching with string replacement.
$Replace = "SW-cache-v{0}" -f (Get-Date -format s)
(Get-Content sw.js) -replace 'SW-cache-v.*',$Replace | Set-Content sw.js
Keep in mind that .* greedily matches all characters until the end of the current line here. For example, if you wanted to only match up until but excluding the next " character, you could use a negated character class [^]:
(Get-Content sw.js) -replace 'SW-cache-v[^"]*',$Replace | Set-Content sw.js
The String.Replace .NET method does a literal string replacement (case-sensitively).
# Wildcards and regex are not allowed with .Replace()
'SW-cache-v extra chars'.Replace('SW-cache-v.*','newstring')
SW-cache-v extra chars
# Literal matching is used by .Replace()
'SW-cache-v.*'.Replace('SW-cache-v.*','newstring')
newstring
-replace defaults to case-insensitive matching. The -creplace operator respects the case.

Change pipe delimited file to comma delimited in Powershell

I have a pipe delimited .TXT file. I need to change the delimiter to a comma instead but still keep the file extension as .TXT. The file looks like this:
Column 1 |Column 2
13|2019-09-30
96|2019-09-26
173|2019-09-25
I am using Windows Powershell 5.1 version for my script.
I am using the following code:
$file = New-Object System.IO.StreamReader -Arg "c:\file.txt"
$outstream = [System.IO.StreamWriter] "c:\out.txt"
while ($line = $file.ReadLine()) {
$s = $line -replace '|', ','
$outstream.WriteLine($s)
}
$file.close()
$outstream.close()
Instead of just replacing the pipe with a comma, the output file looks like this:
C,o,l,u,m,n, 1 , |,C,o,l,u,m,n, 2
1,3,|,2,0,1,9,-,0,9,-,3,0
9,6,|2,0,1,9,-,0,9,-,2,6
1,7,3,|,2,0,1,9,-,0,9,-,2,5
The only problem with your answer is in how you try to replace the | characters in the input:
$s = $line -replace '|', ',' # WRONG
PowerShell's -replace operator expects a regex (regular expression) as its first RHS operand, and | is a regex metacharacter (has special meaning)[1]; to use it as a literal character, you must \-escape it:
# '\'-escape regex metacharacter '|' to treat it literally.
$s = $line -replace '\|', ','
While PowerShell's -replace operator is very flexible, in simple cases such as this one you can alternatively use the [string] type's .Replace() method, which performs literal string replacements and therefore doesn't require escaping (it's also faster than -replace):
# Use literal string replacement.
# Note: .Replace() is case-*sensitive*, unlike -replace
$s = $line.Replace('|', ',')
[1] | denotes an alternation in a regex, meaning that the subexpressions on either side are matched against the input string and one of them matching is sufficient; if your full regex is just |, it effectively matches the empty string before and after each character in the input, which explains your symptom; e.g., 'foo' -replace '|', '#' yields #f#o#o#
You can use Import-Csv and Export-Csv by specifying the -Delimiter.
Import-Csv -Delimiter '|' -Path "c:\file.txt" | Export-Csv -Delimiter ',' -Path "c:\file.txt" -NoTypeInformation
You will find the -split and -join operators to be of interest.
Get-Content -Path "C:\File.TXT" | ForEach-Object { ($_ -split "\|") -join "," } | Set-Content -Path "C:\Out.TXT"

How to count multiple occurrences of a string within another string which contains backslash and double backslash?

I need to count the number of occurrences within a single line from a string that contains backslashes and double backslashes.
I've tried using .Count, but it only counts the first instance within the line. When I try other commands, I usually get some kind of error regarding escape characters.
Here is the one line of data from the file c:\work\test.txt:
Occurrence1\\paul\dfs_app\MyFolder\QA2\testme1 Occurrence2\\paul\dfs_app\MyFolder\QA2\testme2
And here is my code:
$inString = "\\paul\dfs_app\MyFolder\QA2"
$file = "C:\work\test.txt"
$check = Get-Content $file | Where-Object { $_.Contains($inString) }
if ($check.Count -gt 0) {
Write-Host "Found" $check.Count.ToString().PadLeft(2, " ") "occurrences in " $file -ForegroundColor Yellow
}
It returns
Found 1 occurrences in C:\work\test.txt
but it should have found 2 occurrences.
You can use Select-String to count occurrences of $inString.
$out = Select-String -Path $file -Pattern ([regex]::Escape($inString)) -AllMatches
$out.Matches.Count
-Pattern without the -SimpleMatch switch turns the pattern into a regex. Using the Escape() method will automatically escape those backslashes and any other special regex character. Since it is using a regex match rather than a simple match, the matches property will contain each match found. Combining that with the AllMatches parameter, it will continue match searching after the first match on each line.