I have content stored in text file. In that, line 25 has below content
$userid = $null
Now I want to replace this line by
$userid = "Chandru"
I tried with below code but it didn't help me.
$content = Get-content c:\content.text
$oldline = "`$userid = `$null"
$newline = "`$userid = `"chandru`""
$newcontent = $content -replace ("$oldline","$newline")
This doesn't work for me.
"`$userid" escapes the $ for PowerShell. You need to escape the $ for the regular expression:
$oldline = '\$userid = \$null'
$newline = '$userid = "chandru"'
(Get-Content 'C:\content.text') -replace $oldline, $newline
You can use [regex]::Escape() if you want to escape all special characters in a string.
Related
What I have is:
I have made a simple Powershell script to replace the contents of the text files and rewrite the files (UTF8 encoding is crucial):
((Get-Content -path *.adoc -Raw -Encoding utf8) -replace '\[.dfn .term]#.*#','[.dfn .term]_.*_') | Set-Content -Path *.adoc -Encoding utf8
When I tried to run the script like this, I found out that I'm replacing a regex string with a plain text string.
What I want to achieve is:
Find a line that begins with [.dfn .term], has any number of characters between # and #, and replace # with _. Leaving [.dfn .term] and # everything between # unchanged.
I can't replace all # with _ because there can also be text like [.keyword]#something# and it will need replacing # with *. Also, something can be anything - a word or a phrase.
Dealing with patterns and RegEx groups is outside my knowledge. I would appreciate any help.
Example:
I have: A sentence is a string of [.dfn .term]#Words# that has a finished [.keyword]#Thought#. Sentences form [.dfn .term]#Paragraphs#. [.dfn .term]#Paragraphs# form text. Text is cool.
I want to have: A sentence is a string of [.dfn .term]_Words_ that has a finished [.keyword]*Thought*. Sentences form [.dfn .term]_Paragraphs_. [.dfn .term]_Paragraphs_ form text. Text is cool.
use these regex with groups to help you:
$lines = Get-Content -Path C:\file.txt -Encoding UTF8 -Raw
$option = [System.Text.RegularExpressions.RegexOptions]::Singleline
$pattern1 = [regex]::new("(\[\.dfn \.term])#(.*?)#", $option)
#be careful simple quote is important here
$lines = $pattern1.Replace($lines, '$1_$2_')
$pattern2 = [regex]::new("(\[what you want])#(.*?)#", $option)
$lines = $pattern2.Replace($lines, '$1*$2*')
$lines | Set-Content -Path C:\result.txt -Encoding UTF8
test file:
[.dfn .term]#azaeaeae#
[.dfn .term]#errrr# sqsqsqs
[.dfn .term]#errrr# sqsqsqs
eaeaeaeae
aeaeae
[.dfn .term]#errrr# [.keyword]#something# #errrr#
result: (with second pattern .keyword)
[.dfn .term]_azaeaeae_
[.dfn .term]_errrr_ sqsqsqs
[.dfn .term]_errrr_ sqsqsqs
eaeaeaeae
aeaeae
[.dfn .term]_errrr_ [.keyword]*something* #errrr#
you could write too:
$lines = (Get-Content -path C:\yourfile.txt -Raw -Encoding utf8) `
-replace '(\[\.dfn \.term])#(.*?)#', '$1_$2_' `
-replace '(\[\.keyword])#(.*?)#', '$1*$2*'
you could use named groups if you want:
$pattern1 = [regex]::new("(?<begin>\[\.dfn \.term])#(?<text>.*?)#", $option)
#be careful simple quote is important here
$lines = $pattern1.Replace($lines, '${begin}_${text}_')
if you have lot of patterns different, you could put them in an object:
$patterns = #{
'(\[\.dfn \.term])#(.*?)#' = '$1_$2_' ;
'(\[\.keyword])#(.*?)#' = '$1*$2*'
}
$option = [System.Text.RegularExpressions.RegexOptions]::Singleline
foreach($k in $patterns.Keys){
$pat = [regex]::new($k, $option)
$lines = $pat.Replace($lines, $patterns.$k)
}
You want to create a regexp that matches JUST the # symbols following the [.dfn .term] and at the end of the line.
Here's an example:
"[.dfn .term]# everything between #" -replace "(?<=\[\.dfn \.term\])#|#$", "_"
...which results in: [.dfn .term]_ everything between _
Here's how it breaks down:
(?<=[.dfn .term]) - looks for [.dfn .term], but does not match the text. It's called a positive look behind.
# - matches the pound sign
| - OR
#$ - matches the pound sign at the end of the line
I read a file from a program with powershell and want to replace certain strings there. For example, the content of a file looks like this:
<"#319",
#"Sprache" = "DE">
<F5#T#Z7#L1031>5<F5#T#Z7#L1033>)<F5#Z7#L1031><Tab>#319-10002
Now I want to replace e.g. #319-10002 by Some Text, which is no problem.
$output = New-Object System.IO.StreamWriter (Join-Path -Path $outputPath -ChildPath "$outputName.ildoc")
Get-Content -Path (Join-Path -Path $inputPath -ChildPath "$inputName.ildoc") -ReadCount 512 | ForEach-Object {
$value = $_
foreach($entry in $csvInput.GetEnumerator()) {
$value = $value -replace $entry.Name, $entry.Value
}
$output.Write((($value | Out-String) -replace "`r`n", "`n"))
}
$output.Close()
Those "variables" are from a CSV file and are therefore dynamic. There are 2 types:
#Number-Number
#Number-Text
Now there is also the case that the line is longer than 80 characters. Then the program that generated the file automatically inserts a line break after 80 characters.
<"#319",
#"Sprache" = "DE">
<F5#T#Z1#L1031>3<F5#T#Z1#L1033>)<F5#Z1#L127><Tab><F5#Z1#L1031>Some more Text #3
19-10002
Then there is also the case that the string is interrupted by tags. If text is in tables and the text is longer than the column, the program automatically inserts a <SR> followed by a line break at the place of the break.
<Cell, Straddle = 2,
Top Ruling Color = 16,
Left Ruling Weight = 0.75,
Left Ruling Color = 30,
Left Ruling Visible = no><!Page,
Left Margin = 0.0039372 Inches,
Right Margin = 0.0039372 Inches>
<"text:zentr">
#319-10<SR>
002
I am currently quite at a loss how to solve the problem. Do you have an idea how to solve this?
Before applying your replacements you could preprocess the file
to remove the Pos~80 and <SR> breaks with Regular Expressions:
(Get-Content .\input.ildoc -raw) -replace '(?m)(?<=^.{79,})\r?\n' -replace '\<SR\>\r?\n'
yiedls here (with both above samples)
<"#319",
#"Sprache" = "DE">
<F5#T#Z1#L1031>3<F5#T#Z1#L1033>)<F5#Z1#L127><Tab><F5#Z1#L1031>Some more Text #319-10002
<Cell, Straddle = 2,
Top Ruling Color = 16,
Left Ruling Weight = 0.75,
Left Ruling Color = 30,
Left Ruling Visible = no><!Page,
Left Margin = 0.0039372 Inches,
Right Margin = 0.0039372 Inches>
<"text:zentr">
#319-10002
I think you need to tackle this using some cleaning up regexes on the file content first.
Perhaps this could help:
First pass to deal with #Number-Number or #Number-Text broken by line breaks
$content = $content -replace '(#)(?:\r?\n)*(\d+)(?:\r?\n)*([-\w]+)', '$1$2$3'
this changes
<F5#T#Z1#L1031>3<F5#T#Z1#L1033>)<F5#Z1#L127><Tab><F5#Z1#L1031>Some more Text #3
19-10002
<F5#T#Z1#L1031>3<F5#T#Z1#L1033>)<F5#Z1#L127><Tab><F5#Z1#L1031>Some more Text #3
20-TEXT
into
<F5#T#Z1#L1031>3<F5#T#Z1#L1033>)<F5#Z1#L127><Tab><F5#Z1#L1031>Some more Text #319-10002
<F5#T#Z1#L1031>3<F5#T#Z1#L1033>)<F5#Z1#L127><Tab><F5#Z1#L1031>Some more Text #320-TEXT
Second pass deals with <SR> followed by newlines:
$content = $content -replace '(#[-\d]+)<SR>\r?\n([-\w]+)', '$1$2'
this changes stuff like
#319-10<SR>
002
into
#319-10002
After this, the elements to replace should be no longer broken up.
Putting this together, you can try this code:
# get the content of the file as a single string including line breaks
$content = Get-Content -Path (Join-Path -Path $inputPath -ChildPath "$inputName.ildoc") -Raw
# remove garbage linebreaks
$content = $content -replace '(#)(?:\r?\n)*(\d+)(?:\r?\n)*([-\w]+)', '$1$2$3'
# remove garbage <SR>linebreaks
$content = $content -replace '(#[-\d]+)<SR>\r?\n([-\w]+)', '$1$2'
# split the content into an array of strings and loop through
for ($i = 0; $i -lt ($content -split '\r?\n').Count; $i++) {
$line = $content[$i]
foreach($entry in $csvInput.GetEnumerator()) {
$line = $line -replace $entry.Name, $entry.Value
}
# overwrite the string element with the replaced value
$content[$i] = $line
}
# finally write the updated array as string joined with '\n'
Set-Content -Path (Join-Path -Path $outputPath -ChildPath "$outputName.ildoc") -Value ($content -join '\n')
this is what i got so far
if the command places a forth line of output then the regex shouldn't be match, but it does for me.
any ideas?
$From = "cody#tech.com"
$To = "cody#tech.com"
$Subject = "hello"
$Body = "body"
$SMTPServer = "smtp.office365.com"
$SMTPPort = "587"
$Attachment = "c:\checkpointlog.txt"
$RE = [regex]"(?smi)^Checkpointing to checkpoint.*^MD5 \(checkpoint.*^Rotating D:\\Perforce\\Server\\journal to journal.*?$"
$output = p4d -jc
$output | add-content c:\checkpointlog.txt
if ($output -notmatch $RE) {
$param = #{
From = $From
To = $To
Subject = $Subject
Body = $Body
SmtpServer = $SMTPServer
port = $SMTPPort
Usessl = $True
Credential = $cred
Attachments = $Attachment
}
Send-MailMessage #param
Write-Host 'unexpected value, email sent'
exit
}
else {
Write-Host 'continuing script'
}
the output of a Perforce Helix Server command p4 -jc should always be like the following 3 lines:
Checkpointing to checkpoint.22...
MD5 (checkpoint.22) = F561234wer2B8E5123456767745645616D
Rotating D:\Perforce\Server\journal to journal.21...
I would like to use a regex in an if statement so that if the output doesn't match the 3 line string below then an email is sent with the log file for us to inspect.
Checkpointing to checkpoint.*
MD5 (checkpoint.*
Rotating D:\Perforce\Server\journal to journal.*
I am hoping to use a wild card * to account for the incremental number
Any ideas would be great!
Your regex tries to match multiple lines, and therefore needs a single multi-line string as input.
Capturing an external program's output returns an array of strings (lines).
Using an array of string as the LHS of the -match operator causes PowerShell to match the regex against each string individually.
Therefore, join the lines output by p4d with newlines to form a single multi-line string, so that your regex can match multiple lines:
$output = (p4d -jc) -join "`n"
Additionally, if you want to make sure that your regex matches the entire input, not just a substring, restructure you regex as follows:
Remove in-line option m (multi-line) so that ^ and $ truly only match the very start and end of the multi-line string
Remove in-line option s, so that . doesn't match newlines, and match newlines explicitly with \n (instead of ^).
$RE = '(?i)^Checkpointing to checkpoint.*\nMD5 \(checkpoint.*\nRotating D:\\Perforce\\Server\\journal to journal.*$'
Build (and test) your Regular Expression on a website like regex101.com
I suggest to use splatting
$RE = [regex]"(?smi)^Checkpointing to checkpoint.*^MD5 \(checkpoint.*^Rotating D:\\Perforce\\Server\\journal to journal.*?$"
$output = p4d -jc
$output | add-content c:\checkpointlog.txt
if ($output -notmatch $RE) {
$param = #{
From = $From
To = $To
Subject = $Subject
Body = $Body
SmtpServer = $SMTPServer
port = $SMTPPort
Usessl = $True
Credential = $cred
Attachments = 'c:\checkpointlog.txt'
}
Send-MailMessage #param
exit
}
I know you wanted to use RegEx but maybe this would help? It might not be the greatest but it should work.
$file='checkpointlog.txt'
$line1Expected="Checkpointing to checkpoint*"
$line2Expected="MD5 (checkpoint*"
$line3Expected="Rotating D:\Perforce\Server\journal to journal*"
$line1Actual=Get-Content($file) | Select -Index 0
$line2Actual=Get-Content($file) | Select -Index 1
$line3Actual=Get-Content($file) | Select -Index 2
if($line1Actual -like $line1Expected`
-and $line2Actual -like $line2Expected`
-and $line3Actual -like $line3Expected){
}else{
echo 'send mail'
}
I have a string "....\xyz\abc\0.0\abc.def.ghi.jkl.dll" am trying to get the value of a "abc.def.ghi.jkl.dll" into a variable using powershell.
I am totally new to regex and PS and kinda confused on how to get this done. I read various posts about regex and I am unable to get anything to work
Here is my code,
$str = "..\..\xyz\abc\0.0\abc.def.ghi.jkl.dll"
$regex = [regex] '(?is)(?<=\b\\b).*?(?=\b.dll\b)'
$result = $regex.Matches($str)
Write-Host $result
I would like to get "abc.def.ghi.jkl.dll" into $result. Could someone please help me out
You can use the following regex:
(?is)(?<=\\)[^\\]+\.dll\b
See regex demo
And no need to use Matches, just use a -match (or Match).
Explanation:
(?<=\\) - make sure there is a \ right before the current position in string
[^\\]+ - match 1 or more characters other than \
\.dll\b - match a . symbol followed by 3 letters dll that are followed by a trailing word boundary.
Powershell:
$str = "..\..\xyz\abc\0.0\abc.def.ghi.jkl.dll"
[regex]$regex = "(?is)(?<=\\)[^\\]+\.dll\b"
$match = $regex.match($str)
$result = ""
if ($match.Success)
{
$result = $match.Value
Write-Host $result
}
I'm trying to find and replace some text at the end of line with Powershell. (ascii, txt, windows) I need to do this with a given script, which is already used for string replace:
$inputText = [system.IO.File]::ReadAllText("Text.txt")
$regex = '\\DE$|\DE_02'
$regex > test.txt
$th = [system.IO.File]::ReadAllText("test.txt")
foreach($expression in $th) {
if ($expression -eq 'EOF') { break }
$parts = $expression.Split("|")
if ($parts.Count -eq 2) {
$inputText = $InputText -creplace $parts
echo $inputText | out-file "Text_neu.txt" -enc ascii
}
}
The cmdlet works fine so far, but cannot match the end of line ($) -.-
I also tried `r`n instead of $ but didn't work...
When I try like this:
$inputText = [system.IO.File]::ReadAllText("Text.txt")
$inputText.Replace("\DE\`r\`n","\DE_02\`r\`n") | Out-File Text_neu.txt
it's al replaced correctly.
How can I change the existing script so that it will work also?
I am not sure if I understand your script correctly, but I think your problem is, you are replacing on the whole text and not on single rows.
So $ is not the end of a row (\r\n) it will per default match on the end of the string!
You can modify this behaviour by using the inline modifier (?m). This will change the behaviour of $ to match the end of the row.
Try
$regex = '(?m)\\DE$|\DE_02'
as you regular expression.