Powershell rearrange items into a list seperated by comma - powershell

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.

Related

Can I convert a row of comma delimited values to a column

I have one row of temperature data in a text file that I would like to convert to a single column and save as a CSV file using a PowerShell script. The temperatures are separated by commas and look like this:
21,22,22,22,22,22,22,20,19,18,17,16,15,14,13,12,11,10,9,9,9,8,8,9,8,8,8,9,9,8,8,8,9,9,9,8,8,8,8,8,9,10,12,14,15,17,19,20,21,21,21,21,21,21,21,21,21,21,21,20,20,20,20,20,22,24,25,26,27,27,27,28,28,28,29,29,29,28,28,28,28,28,28,27,27,27,27,27,29,30,32,32,32,32,33,34,35,35,34,33,32,32,31,31,30,30,29,29,28,28,27,28,29,31,33,34,35,35,35,36,36,36,36,36,36,36,36,36,37,37,37,37,37,37,38,39,40,42,43,43,43,43,43,42,42,42,41,41,41,41,40,39,37,36,35,34,33,32,31,31,31,31,31,31,31,31,31,31,
I have tried several methods based on searches in this forum I thought this might work but it returns an error: Transpose rows to columns in PowerShell
This is the modified code I tried that returns: Error: "Input string was not in a correct format."
$txt = Get-Content 'C:myfile.txt' | Out-String
$txt -split '(?m)^,\r?\n' | ForEach-Object {
# create empty array
$row = #()
$arr = $_ -split '\r?\n'
$k = 0
for ($n = 0; $n -lt $arr.Count; $n += 2) {
$i = [int]$arr[$n]
# if index from record ($i) is greater than current index ($k) append
# required number of empty fields
for ($j = $k; $j -lt $i-1; $j++) { $row += $null }
$row += $arr[$n+1]
$k = $i
}
$row -join '|'
}
This seems like it should be simple to do with only one row of data. Are there any suggestions on how to convert this single row of numbers to one column?
Try this:
# convert row to column data
$header = 'TEMPERATURE'
$values = $(Get-Content input.dat) -split ','
$header, $values | Out-File result.csv
#now test the result
Import-Csv result.csv
The header is the first line (or record) in the CSV file. In this case it's a single word, because there is only one column.
The values are the items between commas in the input. In this case, the -split on commas generates an array of strings. Note that, if comma is a separator, there will be no comma after the last temperature. Your data doesn't look like that, but I have assumed that the real data does.
Then, we just write the header and the array out to a file. But what happened to all the commas? It turns out that, for a single column CSV file, there are no commas separating fields. So the result is a simple CSV file.
Last, there is a test of the output using Import-csv to read the result and display it in table format.
This isn't necessarily the best way to code it, but it might help a beginner get used to powershell.
Assuming I'm understanding your intent correctly, based on your verbal description (not your own coding attempt):
# Create simplified sample input file
#'
21,22,23,
'# > myfile.txt
# Read the line, split it into tokens by ",", filter out empty elements
# with `-ne ''` (to ignore empty elements, such as would
# result from the trailing "," in your sample input),
# and write to an output CSV file with a column name prepended.
(Get-Content myfile.txt) -split ',' -ne '' |
ForEach-Object -Begin { 'Temperatures' } -Process { $_ } |
Set-Content out.csv
More concise alternative, using an expandable (interpolating) here-string:
# Note: .TrimEnd(',') removes any trailing "," from the input.
# Your sample input suggests that this is necessary.
# If there are no trailing "," chars., you can omit this call.
#"
Temperatures
$((Get-Content myfile.txt).TrimEnd(',') -split ',' -join [Environment]::NewLine)
"# > out.csv
out.csv then contains:
Temperatures
21
22
23

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 { $_ }
}

does not work split on 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]

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.

PowerShell script to convert one-column CSV file

I'm looking for a script, doesn't have to be in PS but must run under Windows, that converts a one column text file like below
abc
def
ghi
into
'abc',
'def',
'ghi'
I'm currently making this change in Excel using =concatenate, but a script would be better.
Use can use a regular expression to insert characters at beginning and end.
get-content ./myonlinecolumn.txt | foreach {$_ -replace "^","'" -replace "`$","',"}
Or you could use the format operator -f:
get-content ./myonlinecolumn.txt | foreach {"'{0}'," -f $_ }
Its a bit more work to remove the last trailing comma, but this also possible
$a = get-content ./myonlinecolumn.txt
get-content ./myonlinecolumn.txt | foreach { if ($_.readcount -lt $a.count) {"'{0}'," -f $_ } else {"'{0}'" -f $_ }}
My first idea was similar to what Chad already wrote, that is a check on the line number. So I've tried a different solution. Not very nice but I post it too :)
((gc c:\before.txt | % {"'"+$_+"'"} ) -join ",*").split("*") | out-file c:\after.txt
You can just use
(gc myfile | %{"'$_'"}) -join ',
'
or, if you love escapes:
(gc myfile | %{"'$_'"}) -join ",`n"
This loads the file into an array of strings (Get-Content), then processes each string by putting it into single quotes. (Use `"'$($_.Trim())'" if you need to trim whitespace, too). Then the lines are joined with a comma and line break (those can be embedded directly into strings).
If your values can contain single quotes (which need to be escaped) it's trivial to stick that in there, too:
(gc myfile | %{"'$($_.Trim() -replace "'","''")'"}) -join ",`n"