How pipe after replace in PowerShell? - powershell

I would like a to replace characters inside a string and then split it.
Example below:
$in = "string with spaces"
$out = $in -replace 's' | $_.Split(' ')
Leads to ExpressionsMustBeFirstInPipeline.
How come this doesn't work?

There's nothing wrong with the result of the replacement going into the pipeline, but your next step doesn't actually read from the pipeline. For the construct you chose you need a ForEach-Object loop:
$out = $in -replace 's' | ForEach-Object { $_.Split(' ') }
or call Split() on the result of the replacement (without pipeline):
$out = ($in -replace 's').Split(' ')
However, if you use the -split operator instead of the Split() method you can simply daisy-chain it (again without using the pipeline):
$out = $in -replace 's' -split ' '

try this
$in = "string with spaces"
$out = $in -split ' ' -replace 's'
echo $out

You can use the Replace string method instead. E.g to replace s with blank, and then split on space:
$out = $in.Replace('s','').split(' ')

Related

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"

replace whole string if contains substring

I want to completely replace a string if it contains a specific substring, using replace. How can this be done?
I have tried the following, with expected output "STRING":
$a="abc123STRINGabc123"
$a.replace('*STRING*','STRING')
Use the -replace operator and a regular expression.
$a = 'abc123STRINGabc123'
$b = 'abc123foobarabc123'
$srch = 'STRING'
$repl = 'GNIRTS'
$pattern = '.*{0}.*' -f [regex]::Escape($srch)
$a -replace $pattern, $repl # output: GNIRTS
$b -replace $pattern, $repl # output: abc123foobarabc123

using matched patterns in powershell -replace

The following prints out 123$replace456, I'd like it to print 123yyy456. How do I do this in powershell?
$path = '123xxx456'
$search = "(\d*)xxx(\d*)"
$replace = 'yyy'
$path -replace $search, '$1$replace$2'
Use a double-quoted string for the replacement pattern in order for $replace to expand correctly. Remember to escape the $ in front of backreferences (ie `$1):
$path -replace $search, "`$1$replace`$2"

Swap last.first to first.last in text file

I am trying to swap two words in a string. I currently have a txt file with a column of users formatted last.first. How can I swap that to first.last?
-split the string and concatenate:
$Last,$First = "Lastname.Firstname" -split '\.'
$newString = "$First.$Last"
or use -replace to reorder the two:
"Lastname.Firstname" -replace '(\w+)\.(\w+)','$2.$1'
gc .\names.txt |% { "{1}.{0}" -f $_.split('.') }
Get the lines out of the file with gc which is an alias for Get-Content
Loop over them with % which is an alias for ForEach-Object
Split() each line around the full stop, into an array of two items
Use the "" -f string formatting operator to build a string taking array items in the order 1, 0 which swaps the order of the parts.
Quick and dirty - minimal error checking...
Get-Content .\test.txt |
ForEach-Object {
if ( $_.Contains('.') ) {
$_.Split('.')[1] + '.' + $_.Split('.')[0] }
else { $_ }
}

Powershell: Find and replace words split by newline

So I have a text file that looks something like this:
Members : {USER\member1, USER\member2, US
ER\member3, USER\member4, USER
\member5, USER\member6}
and I would like to remove USER\. The following code removes it but not when it's split by a newline, for example when US on one line and ER\ on another line.
Foreach-Object { %{$_.Replace('USER\', '') }
Putting `n or `r in there doesn't work. Any help is appreciated.
Try this:
PS > ((Get-Content .\t.txt) | % { $_.Trim() }) -join "" -replace "USER\\"
Members : {member1, member2, member3, member4, member5, member6}
If the text is in a string-array, switch out (Get-Content .\t.txt) with your variable. If you have the text in a string(not array) variable, use:
($MYSTRINGVAR.Split("`r`n") | % { $_.Trim() }) -join "" -replace "USER\\"
EDIT Just modify the "Members" part:
$text = (Get-Content .\input.txt) -join "`r`n"
($text | Select-String '(?s)(?<=Members : \{)(.+?)(?=\})' -AllMatches).Matches | % {
$text = $text.Replace($_.Value, ($_.Value -split "`r`n" | % { $_.Trim() }) -join "" -replace "USER\\")
}
$text | Set-Content output.txt
There are probably easier ways to get there, but you can give this one a try:
$Text = #'
Members : {USER\member1, USER\member2, US
ER\member3, USER\member4, USER
\member5, USER\member6}
'#
# First - USER\ with newline inside..
foreach ($index in 1..4) {
$Text = $Text -replace ('USER\\'.Insert($index,'(\r\n\s+)')), '$1'
}
# Than - pure USER\
$Text = $Text -replace 'USER\\'
$Text
As you can see I create few patterns that contain and keep that element in results (, '$1'). For simple ones - I just remove USER\
I've used herestring to create text to work with, it's possible that \r may not be needed for actual file.
This is actually just a comment to Graimer's solution, but it would've been too long and also not readable enough as a comment, so I'm making it a (supplementary) answer instead.
To re-wrap the string after removing USER\ you could do something like this:
$s = "Members : {member1, member2, member3, member4, member5, member6}"
$s -match '^(.*?{)(.*)(})$'
$pad = " " * $matches[1].Length
$matches[1] + ($matches[2] -replace '(.{1,20},) ', "`$1`r`n$pad") + $matches[3]
The first regular expression splits the string into 3 parts that can be accessed via the $matches collection:
Name Value
---- -----
3 }
2 member1, member2, member3, member4, member5, member6
1 Members : {
0 Members : {member1, member2, member3, member4, member5, member6}
$matches[1] is the prologue including the opening curly bracket, $matches[2] is the member list, and $matches[3] is the closing curly bracket. Now you only need to wrap $matches[2] at whatever length you want:
'(.*{1,20},) '
The above means "longest match of at most 20 characters followed by a comma and a space". Replace that with the 1st group ($1) followed by a line-break (```rn``) and a number of spaces that matches the length of the prologue ($pad`) and glue it back together with prologue and trailing curly bracket.