does not work split on powershell - powershell

I have code, which split string to array. So can you help me, why this is doesn't work?
$var="test.1->test.2"
$arr=$var.Split("->")
$arr[0]#show correct: "test.1"
$arr[1]#doesn't show...

The string Split() method takes an array of characters and splits the string on any character that is in the array. Powershell also has a -split operator that takes a delimiter. I think you probably wanted to use the -split operator here.
Here's the difference. The first splits at both the '-' and the '>', the second splits on the '->':
PS C:\> $var.Split("->")
test.1
test.2
PS C:\> $var -split "->"
test.1
test.2
Note that split takes a regular expression pattern rather than a simple string. While that is fine for this particular pattern other punctuation could provide problems requiring you to escape special characters in the pattern or use the SimpleMatch option:
PS C:\> "a[b" -split "[",0,"SimpleMatch"
a
b

It works. But it did split the string by "-" OR ">", so $arr[1] has empty string between "-" and ">", and "test.2" is in $arr[2].
So you can either:
$var="test.1->test.2"
$arr=$var.Split("->")
write-host $arr[0]
write-host $arr[2]
or:
$var="test.1->test.2"
$arr=$var.Split("->") | select -First 1 -Last 1
write-host $arr[0]
write-host $arr[1]
or something like:
$var="test.1->test.2"
$arr= $($var -replace "->","#").Split("#")
write-host $arr[0]
write-host $arr[1]

Related

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

Failing to get Substring from Path in 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('\')))"

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"

Powershell rearrange items into a list seperated by comma

I have a variable which contains a number of items. For example,
PS C:\Users\Administrator\Desktop> $a
OU=Computers,DC=lala
OU=tset,DC=eat
How do I put the items together into a single string and separated by comma and each item with double quote? Here is the output I expect:
PS C:\Users\Administrator\Desktop> $a
"OU=Computers,DC=lala","OU=tset,DC=eat"
Try this. This is not the good programming example but it will give the required output:
$newData= $a |% {"$("OU="+$_.OU),$("DC="+$_.DC)"}
$newData
If you have an array, you can try this:
($a | % { '"{0}"' -f $_ }) -join ","
Each element of the array is reformatted and the resulting stream is passed to the -join operator to concatenate with commas.
If you have a single string with embedded CRLF, try this:
(($a -split '\r\n') | % { '"{0}"' -f $_ }) -join ","
Here, we split the string into an array before passing it through the same logic as in the first example.

replace a string in a csv file with powershell

I need to place System.Object[] for some columns in a csv file. I tried 3 different method but none of them are working. System.Object[] is put in by powershell when that object is empty or something.
$file = "c:\output.csv"
(gc $file) -replace "'system.object[]'", ""
[io.file]::readalltext($file).replace("'system.object[]'","")
(Get-Content $file | ForEach-Object { $_ -replace "system.object[]", "" } ) | Set-Content $file
I added following code to the variable that containing System.Object[] on output. and it's seems to be working. and now I dont have to do the replacement at file level.
"Access Code" = (#($AccessCode) | Out-String).Trim()
The bracers and the dot ([, ], .) need all to be escaped. Furthermore remove the double quotation marks, just keep the single ones. Also think about using creplace, in case you want to work case insensitive. So the command would look like this:
(gc $file) -replace 'system\.object\[\]', ''
In case you want to write everything to a new file:
(gc $file) -replace 'system\.object\[\]', ''|out-file "test2.txt" -encoding ASCII
Just use Escape character
(gc $file) -replace 'system.object\[\]', ""
The characters '[' and ']' are used for Regex pattern. You must use Escape
character '\' to tell Powershell that This is a regular chars