Replace string with line break with another string in Powershell - powershell

I want to replace
$fieldTool.GetFieldValue($i
tem,"Title")
with
{{(sc_get_field_value i_item 'Title')}}
The original string has a line break and I am using 'n like this $fieldTool.GetFieldValue($i'ntem,"Title")
This is the code
$template = '<div class="tile-inspiration__title field-title">$fieldTool.GetFieldValue($i
tem,"Title")</div>'
$matchString = '$fieldTool.GetFieldValue($i'ntem,"Title")'
$pattern = $([regex]::escape($matchString))
$replaceString = "{{(sc_get_field_value i_item 'Title')}}"
$newtemplate = $template -replace $pattern, $replaceString
Write-Host $newtemplate
The above code is not working. How can I replace the string with line break with another string.
Any suggestion would be appreciated.
Thanks in advance

To replace newlines, you should use regex pattern \r?\n. This will match both *nix as well as Windows newlines.
In your template string however, there are multiple characters that have special meaning in regex, therefore you need to do [regex]::Escape(), but that also would wrongfully escape the characters \r?\n, rendering it as \\r\?\\n, so adding that in the $matchString before escaping it, would be of no use.
You can manually first replace the newline with a character that otherwise is not present in the $matchString and has no special meaning in regex.
$template = '<div class="tile-inspiration__title field-title">$fieldTool.GetFieldValue($i
tem,"Title")</div>'
# for demo, I chose to replace the newline with an underscore
$matchString = '$fieldTool.GetFieldValue($i_tem,"Title")'
# now, escape the string and after that replace the underscore by the wanted \r?\n pattern
$pattern = [regex]::escape($matchString) -replace '_', '\r?\n'
# $pattern is now: \$fieldTool\.GetFieldValue\(\$i\r?\ntem,"Title"\)
$replaceString = "{{(sc_get_field_value i_item 'Title')}}"
# this time, the replacement should work
$newtemplate = $template -replace $pattern, $replaceString
Write-Host $newtemplate # --> <div class="tile-inspiration__title field-title">{{(sc_get_field_value i_item 'Title')}}</div>

Related

How do I replace the first occurrence of a period in a powershell string?

I have the following PowerShell:
$img="john.smith.jpg"
$img.Replace(".", "")
I'm trying to replace the first occurrence of a a period in the string.
At the moment it replaces all periods and returns: "johnsmithjpg"
The output I'm looking for is: "johnsmith.jpg".
I also tried the following but it doesn't work:
$img="john.smith.jpg"
[regex]$pattern = "."
$img.replace($img, "", 1)
What do I need to do to get it to only replace the first period?
From Replacing only the first occurrence of a word in a string:
$img = "john.smith.jpg"
[regex]$pattern = "\."
$img = $pattern.replace($img, "", 1)
Output:
Note for the pattern, . is treated as a wildcard character in regex, so you need to escape it with \
Other possibility without RegEx
$img="john.smith.jpg"
$img.Remove($img.IndexOf("."),1)
Seems to me that $img contains a filename including the extension. By blindly replacing the first dot, you might end up with unusable (file)names.
For instance, if you have $img = 'johnsmith.jpg' (so the first and only dot there is part of the extension), you may end up with johnsmithjpg..
If $img is obtained via the Name property of a FileInfo object (like Get-Item or Get-ChildItem produces),
change to:
$theFileInfoObject = Get-Item -Path 'Path\To\johnsmith.jpg' # with or without dot in the BaseName
$img = '{0}{1}' -f (($theFileInfoObject.BaseName -split '\.', 2) -join ''), $theFileInfoObject.Extension
# --> 'johnsmith.jpg'
Or use .Net:
$img = "johnsmith.jpg" # with or without dot in the BaseName
$img = '{0}{1}' -f (([IO.Path]::GetFileNameWithoutExtension($img) -split '\.', 2) -join ''), [IO.Path]::GetExtension($img)
# --> 'johnsmith.jpg'

add quotation mark to a text file powershell

I need to add the quotation mark to a text file that contains 500 lines text.
The format is inconsistent. It has dashes, dots, numbers, and letters. For example
1527c705-839a-4832-9118-54d4Bd6a0c89
16575getfireshot.com.FireShotCaptureWebpageScreens
3EA2211E.GestetnerDriverUtility
I have tried to code this
$Flist = Get-Content "$home\$user\appfiles\out.txt"
$Flist | %{$_ -replace '^(.*?)', '"'}
I got the result which only added to the beginning of a line.
"Microsoft.WinJS.2.0
The expected result should be
"Microsoft.WinJS.2.0"
How to add quotation-mark to the end of each line as well?
There is no strict need to use a regex (regular expression) in your case (requires PSv4+):
(Get-Content $home\$user\appfiles\out.txt).ForEach({ '"{0}"' -f $_ })
Array method .ForEach() processes each input line via the script block ({ ... }) passed to it.
'"{0}"' -f $_ effectively encloses each input line ($_) in double quotes, via -f, the string-format operator.
If you did want to use a regex:
(Get-Content $home\$user\appfiles\out.txt) -replace '^|$', '"'
Regex ^|$ matches both the start (^) and the end ($) of the input string and replaces both with a " char., effectively enclosing the input string in double quotes.
As for what you tried:
^(.*?)
just matches the very start of the string (^), and nothing else, given that .*? - due to using the non-greedy duplication symbol ? - matches nothing else.
Therefore, replacing what matched with " only placed a " at the start of the input string, not also at the end.
You can use regex to match both:
The beginning of the line ^(.*?)
OR |
The End of the line $
I.e. ^(.*?)|$
$Flist = Get-Content "$home\$user\appfiles\out.txt"
$Flist | %{$_ -replace '^(.*?)|$', '"'}

Powershell replace last two occurrences of a '/' in file path with '.'

I have a filepath, and I'm trying to remove the last two occurrences of the / character into . and also completely remove the '{}' via Powershell to then turn that into a variable.
So, turn this:
xxx-xxx-xx\xxxxxxx\x\{xxxx-xxxxx-xxxx}\xxxxx\xxxxx
Into this:
xxx-xxx-xx\xxxxxxx\x\xxxx-xxxxx-xxxx.xxxxx.xxxxx
I've tried to get this working with the replace cmdlet, but this seems to focus more on replacing all occurrences or the first/last occurrence, which isn't my issue. Any guidance would be appreciated!
Edit:
So, I have an excel file and i'm creating a powershell script that uses a for each loop over every row, which amounts to thousands of entries. For each of those entries, I want to create a secondary variable that will take the full path, and save that path minus the last two slashes. Here's the portion of the script that i'm working on:
Foreach($script in $roboSource)
{
$logFileName = "$($script.a).txt".Replace('(?<=^[^\]+-[^\]+)-','.')
}
$script.a will output thousands of entries in this format:
xxx-xxx-xx\xxxxxxx\x{xxxx-xxxxx-xxxx}\xxxxx\xxxxx
Which is expected.
I want $logFileName to output this:
xxx-xxx-xx\xxxxxxx\x\xxxx-xxxxx-xxxx.xxxxx.xxxxx
I'm just starting to understand regex, and I believe the capture group between the parenthesis should be catching at least one of the '\', but testing attempts show no changes after adding the replace+regex.
Please let me know if I can provide more info.
Thanks!
You can do this in two fairly simply -replace operations:
Remove { and }
Replace the last two \:
$str = 'xxx-xxx-xx\xxxxxxx\x\{xxxx-xxxxx-xxxx}\xxxxx\xxxxx'
$str -replace '[{}]' -replace '\\([^\\]*)\\([^\\]*)$','.$1.$2'
The second pattern matches:
\\ # 1 literal '\'
( # open first capture group
[^\\]* # 0 or more non-'\' characters
) # close first capture group
\\ # 1 literal '\'
( # open second capture group
[^\\]* # 0 or more non-'\' characters
) # close second capture group
$ # end of string
Which we replace with the first and second capture group values, but with . before, instead of \: .$1.$2
If you're using PowerShell Core version 6.1 or newer, you can also take advantage of right-to-left -split:
($str -replace '[{}]' -split '\\',-3) -join '.'
-split '\\',-3 has the same effect as -split '\\',3, but splitting from the right rather than the left.
A 2-step approach is simplest in this case:
# Input string.
$str = 'xxx-xxx-xx\xxxxxxx\x\{xxxx-xxxxx-xxxx}\xxxxx\xxxxx'
# Get everything before the "{"
$prefix = $str -replace '\{.+'
# Get everything starting with the "{", remove "{ and "}",
# and replace "\" with "."
$suffix = $str.Substring($prefix.Length) -replace '[{}]' -replace '\\', '.'
# Output the combined result (or assign to $logFileName)
$prefix + $suffix
If you wanted to do it with a single -replace operation (with nesting), things get more complicated:
Note: This solution requires PowerShell Core (v6.1+)
$str -replace '(.+)\{(.+)\}(.+)',
{ $_.Groups[1].Value + $_.Groups[2].Value + ($_.Groups[3].Value -replace '\\', '.') }
Also see the elegant PS-Core-only -split based solution with a negative index (to split only a fixed number of tokens off the end) in Mathias R. Jessen's helpful answer.
try this
$str='xxx-xxx-xx\xxxxxxx\x\{xxxx-xxxxx-xxxx}\xxxxx\xxxxx'
#remove bracket and split for get array
$Array=$str -replace '[{}]' -split '\\'
#take all element except 2 last elements, and concat after last elems
"{0}.{1}.{2}" -f ($Array[0..($Array.Length -3)] -join '\'), $Array[-2], $Array[-1]

Powershell replace between start and end

I need to replace everything between two points.
$import = Get-Content C:\bookmarks.html
$newbody = Get-Content C:\newbookmarks.html
$remove = '(?<=<DT><H3 ADD_DATE=""1544626193"" LAST_MODIFIED=""154649885"">Import-IE</H3>).*?(?=</DL>)'
$import | %{$_.replace($remove,"$newbody")}
My problem is to get all content between start:
<DT><H3 ADD_DATE=""1544626193"" LAST_MODIFIED=""154649885"">Import-IE</H3>
and the end:
</DL>
incl multiple lines
Example html:
<DT><H3 ADD_DATE="1544626193" LAST_MODIFIED="1546498855">Import-IE</H3>
<DL><p>
<DT>golem.de
<DT>heise online
</DL>
Regards
A couple of changes needed to make this work:
One big multiline string
Since you want to do a replace over multiple lines, we need to makes sure all the lines are contained in the same string, so let's start with that - we can use the -Raw parameter switch with Get-Content:
$import = Get-Content C:\bookmarks.html -Raw
Exact pattern matching in regex
Next up we have the regex pattern itself - there's a few discrepancies between that and the sample content you've shown:
LAST_MODIFIED=""154649885"" # pattern has nested double-quotes and only one 5 at the end
LAST_MODIFIED="1546498855" # input uses just one pair of double-quotes and value has two 5's at the end
So let's fix that, and make sure the input string we're looking for is properly escaped while we're at it:
$remove = "(?<=$([regex]::Escape('<DT><H3 ADD_DATE="1544626193" LAST_MODIFIED="1546498855">Import-IE</H3>'))).*?(?=</DL>)"
String.Replace doesn't support regex
Then, we'll have to abandon the String.Replace() method that you're currently using - because it doesn't actually support regex - so we'll use the -replace operator instead:
$import -replace $remove,"$newbody"
Use -replace in SingleLine mode
The only thing we need now, is to instruct the regex parser to treat the input in SingleLine mode - so that .*? will capture newlines as well. This is super easy though, we just add an options flag s at the start of the regex pattern:
$import -replace "(?s)$remove","$newbody"
And that's it :)
$import = Get-Content C:\bookmarks.html -Raw
$newbody = Get-Content C:\newbookmarks.html
$remove = "(?<=$([regex]::Escape('<DT><H3 ADD_DATE="1544626193" LAST_MODIFIED="1546498855">Import-IE</H3>'))).*?(?=</DL>)"
$import -replace "(?s)$remove","$newbody"

Edit text between two lines using powershell

I want to change this text
PortNumber=10001
;UserName=xxxxxxxxx
;Password=xxxxxxxxx
CiPdfPath=xxxxx
into this
PortNumber=10001
UserName=xxxxxxxxx
Password=xxxxxxxxx
CiPdfPath=xxxxx
I cannot simply search for ;Username=xxxx and ;Password=xxxx because they exist multiple times in the file and need to be commented on some places.
I found the next command
$file = Get-Content "Test.ini" -raw
$file -replace "(?m)^PortNumber=10001[\n\r]+;UserName=xxxx[\r\n]+;Password=xxxx","PortNumber=10001 `r`nUserName=xxxxx`r`nPassword=xxxxx"
And it worked!
But maybe it can be simplyfied
If you use the (?ms) (multiline-singleline) option and here-strings, you can do most of the work with copy/paste:
$string =
#'
PortNumber=10001
;UserName=xxxxxxxxx
;Password=xxxxxxxxx
CiPdfPath=xxxxx
'#
$regex =
#'
(?ms)PortNumber=10001
;UserName=xxxxxxxxx
;Password=xxxxxxxxx
CiPdfPath=xxxxx
'#
$replace =
#'
PortNumber=10001
UserName=xxxxxxxxx
Password=xxxxxxxxx
CiPdfPath=xxxxx
'#
$string -replace $regex,$replace
PortNumber=10001
UserName=xxxxxxxxx
Password=xxxxxxxxx
CiPdfPath=xxxxx
Why don't you search full text which you'd like to replace?
So find:
PortNumber=10001
;UserName=xxxxxxxxx
;Password=xxxxxxxxx
CiPdfPath=xxxxx
and replace with:
PortNumber=10001
UserName=xxxxxxxxx
Password=xxxxxxxxx
CiPdfPath=xxxxx
You can use regular expression to express irrelevant characters
http://www.regular-expressions.info/powershell.html
http://www.powershelladmin.com/wiki/Powershell_regular_expressions
You could use Regex.
Or even simpler, depending on your requirement;
If you know the linenumber of the lines you want to replace, you could easily do this do replace the certain lines:
Given that the file format is the text you've pasted (e.g. username on line 2 and password on line 3), read the file into a line buffer. Replace line 2 and 3 and set the content back to the file.
$lines=(Get-Content .\Test.txt)
$lines[1]= $lines[1].Replace(";","")
$lines[2]= $lines[2].Replace(";","")
$lines|Set-Content .\Test.txt
I might be misunderstading the nature of the question but are you not simply trying to remove the leading semicolons? Is it important to seach for those strings exclusivley?
$file = Get-Content "Test.ini" -raw
$file -replace "(?sm)^;"
$file -replace "(?smi)^;(?=(username|password))"
Both examples should produce the same output. The first will match all leading semicolons. The second will match leading semicolons if the are followed, using a lookahead, by either username or password.