PowerShell index[0] to the first instance of the string, index[1] to the second instance and so on till finished - powershell

For example, replace LINE2 1243 with LINE2 1 because it is on line 1 of test.txt.
# Find the line number:
$lines = sls "LINE2" test.txt | Select-Object -ExpandProperty LineNumber
test.txt:
abc LINE2 1243
lmn LINE2 1250
xyz LINE2 1255
Using:
gc test.txt | % { $_ -replace "LINE2.*", "LINE2 $lines" }
I get:
abc LINE2 1 2 3
lmn LINE2 1 2 3
xyz LINE2 1 2 3
How do I supply index[0], and only index[0], to the first instance of the string, index[1] to the second instance and so on till finished.
Doing it another way:
foreach ($line in $lines){
gc test.txt | % { $_ -replace "LINE2.*", "LINE2 $line" }
}
I get:
abc LINE2 1
lmn LINE2 1
xyz LINE2 1
abc LINE2 2
lmn LINE2 2
xyz LINE2 2
abc LINE2 3
lmn LINE2 3
xyz LINE2 3
How do I get index[0] to only the first instance of the string and so on.

You could use a for loop with an index to achieve this (If I got you right) ;-)
$lines = Select-String "LINE2" -Path C:\sample\test.txt | Select-Object -ExpandProperty LineNumber
Get-Content -Path C:\sample\test.txt -OutVariable Content
for ($index = 0; $index -lt $lines.count; $index++) {
$Content[$index] -replace "LINE2.*", "LINE2 $($lines[$index])"
}
Output:
abc LINE2 1
lmn LINE2 2
xyz LINE2 3

this is a somewhat different way to do things. [grin] what is does ...
reads in the file
i faked this with a here-string, but use Get-Content when doing this for real.
gets the matching lines
it uses the way that -match works against a collection to pull the lines that match the target.
splits on the spaces
selects the 1st two items from that array
adds a $Counter to the collection
joins the three items with a space delimiter
sends the resulting line to the $Results collection
shows that collection on screen
saves it to a text file
here's the code ...
# fake reading in a text file
# in real life, use Get-Content
$InStuff = #'
cba line1 1234
abc LINE2 1243
mnl line4 1244
lmn LINE2 1250
zyx line9 1251
xyz LINE2 1255
qwe line9 1266
'# -split [environment]::NewLine
$Target = 'Line2'
$Counter = 1
$Results = foreach ($IS_Item in ($InStuff -match $Target))
{
$IS_Item.Split(' ')[0..-1] + $Counter -join ' '
$Counter ++
}
# on screen
$Results
# to a file
$Results |
Set-Content -LiteralPath "$env:TEMP\somebadhat.txt"
on screen ...
abc 1243 1
lmn 1250 2
xyz 1255 3
in the text file ...
abc 1243 1
lmn 1250 2
xyz 1255 3

Related

powershell - delete n lines after match in file

my test file looks like this:
aa
xxxxx test1 vraarxxxerv
remove1
remove2
remove3
must stay 1
aaaaaa
aaa
aaaaa
aaaaaaaa
aa
test2
remove1 efsd
remove2 esf
remove3 gr rgsv
must stay 2
aaaaaa
aaa
aaaaa
aaaaaaaa
aa
xx test3
remove1 efsd
remove2 esf
remove3 gr rgsv
must stay 3
aaaaaa
aaa
aaaaa
aaaaaaaa
aa
idea is simple - look for lines contains string test1, test2 and test3 and remove 3 next lines
my code is
$search =
'test1',
'test2',
'test3'
foreach ($item in $search) {
echo "."
$linenumber= Get-Content .\test.txt | select-string $item
$linenumber.LineNumber
Get-Content .\test.txt | Where-Object {
-not ($_.ReadCount -ge $linenumber.LineNumber -and $_.ReadCount -le $linenumber.LineNumber+3)
} | Out-File -FilePath .\test.txt
}
but it just create empty test.txt file - what am I doing wrong..? I would like to have file where remove1 remove2 and remove3 lines are not existing - they are always different so I cannot look for "remove" text, they are just an examples. must stay 1,2,3 lines are just to be sure that it haven't deleted more lines as I need...
Try this:
$lines = Get-Content .\test.txt
$rem = #()
#("test1","test2","test3") | Foreach {
$rem += $lines[(($lines | Select-String -Pattern "$_").LineNumber)..(($lines | Select-String -Pattern "$_").LineNumber+2)]
}
Compare-Object $lines $rem | Select-Object -ExpandProperty InputObject | Set-Content .\test.txt
You could use a switch statement and implement a little state machine to skip the lines you'd like to remove
$state=0
switch -File test.txt -Regex ($_) {
'test[123]' {
$state = 1
Write-Output $_
Continue
}
default {
if ($state -eq 0) {Write-Output $_}
elseif ($state -lt 4) {$state++}
else {$state = 0; Write-Output $_}
}
}
Example
$state=0
#'
aa
xxxxx test1 vraarxxxerv
remove1
remove2
remove3
must stay 1
aaaaaa
aaa
aaaaa
aaaaaaaa
aa
test2
remove1 efsd
remove2 esf
remove3 gr rgsv
must stay 2
aaaaaa
aaa
aaaaa
aaaaaaaa
aa
xx test3
remove1 efsd
remove2 esf
remove3 gr rgsv
must stay 3
aaaaaa
aaa
aaaaa
aaaaaaaa
aa
'# -split "`r`n" | % {
switch -Regex ($_) {
'test[123]' {
$state = 1
Write-Output $_
Continue
}
default {
if ($state -eq 0) {Write-Output $_}
elseif ($state -lt 4) {$state++}
else {$state = 0; Write-Output $_}
}
}
}
returns
aa
xxxxx test1 vraarxxxerv
must stay 1
aaaaaa
aaa
aaaaa
aaaaaaaa
aa
test2
must stay 2
aaaaaa
aaa
aaaaa
aaaaaaaa
aa
xx test3
must stay 3
aaaaaa
aaa
aaaaa
aaaaaaaa
aa

Import-CSV does not preserve line indents

I am using Import-CSV to get the data from a csv file that looks like:
P1,1,3,4
P2,4,5,6
P3,1,2,3
P4,8.7,6,3
I would like to keep the white-space in front of the text as it indicates the hierarchy. Import-CSV returns:
P1,1,3,4
P2,4,5,6
P3,1,2,3
P4,8.7,6,3
Is there a way to keep the white space?
Your CSV isn't correctly formatted, the items in each row should all be quoted to meet the file specification:
"P1,"1","3","4"
" P2,"4","5","6"
" P3,"1","2","3"
" P4,"8.7","6","3"
You can take a shortcut and only wrap the entries with leading spaces in quotes:
P1,1,3,4
" P2",4,5,6
" P3",1,2,3
" P4",8.7,6,3
Then Import-CSV will function as you're expecting, headers added for demonstration:
Import-CSV leading_spaces.csv -Header "Field1","Field2","Field3","Field4"
Gives you your desired output:
Field1 Field2 Field3 Field4
------ ------ ------ ------
P1 1 3 4
P2 4 5 6
P3 1 2 3
P4 8.7 6 3
As per James C's comment, you can do this with Get-Content:
$myData = Get-Content .\test2.txt
foreach($line in ($myData | Select-Object -Skip 1)){
[array]$results += [pscustomobject]#{
$myData[0].Split(",")[0] = $line.Split(",")[0]
$myData[0].Split(",")[1] = $line.Split(",")[1]
$myData[0].Split(",")[2] = $line.Split(",")[2]
$myData[0].Split(",")[3] = $line.Split(",")[3]
}
}
Maybe this will help, it will create a new object for each row:
get-content test.csv | % {
$row = New-Object PSObject
$i = 0
$_ -split "," | %{
$row | add-member Noteproperty "column$i" $_
$i++
}
$row
}
Output will look like this:
column0 column1 column2 column3
------- ------- ------- -------
P1 1 3 4
P2 4 5 6
P3 1 2 3
P4 8.7 6 3

How to transpose one column (multiple rows) to multiple columns?

I have a file with the below contents:
0
ABC
1
181.12
2
05/07/16
3
1002
4
1211511108
6
1902
7
1902
10
hello
-1
0
ABC
1
1333.21
2
02/02/16
3
1294
4
1202514258
6
1294
7
1294
10
HAI
-1
...
I want to transpose the above file contents like below. The '-1' in above lists is the record separator which indicates the start of the next record.
ABC,181.12,05/07/16,1002,1211511108,1902,1902,hello
ABC,1333.21,02/02/16,1294,1202514258,1294,1294,HAI
...
Please let me know how to achieve this.
Read the file as a single string:
$txt = Get-Content 'C:\path\to\your.txt' | Out-String
Split the content at -1 lines:
$txt -split '(?m)^-1\r?\n'
Split each block at line breaks:
... | ForEach-Object {
$arr = $_ -split '\r?\n'
}
Select the values at odd indexes (skip the number lines) and join them by commas:
$indexes = 1..$($arr.Count - 1) | Where-Object { ($_ % 2) -ne 0 }
$arr[$indexes] -join ','

Replace white spaces in strings in a pipe in PowerShell

I have the following in PowerShell:
$objects = git -C "$localRepoPath" verify-pack -v (Get-ChildItem "$PackFiles\pack-*.idx")`
| Select-String -Pattern "blob"`
| Select -First 5
# Output each line
$objects | % {
$_.Line
}
When I run the above I get:
1ff0c423042b46cb1d617b81efb715defbe8054d blob 2518 701 5081449
dc9a583bf4927685d9ceb3f9381b6a232a609281 blob 2390 1203 5082150
876f3b37e51d0af2d090104e22352171eca12bff blob 11 40 5083353 1 dc9a583bf4927685d9ceb3f9381b6a232a609281
3faa5832a9e087a5d4cf2b493c52f97eda478242 blob 21 51 5083393 2 876f3b37e51d0af2d090104e22352171eca12bff
15a0d10cde33f1d3fe5c2acda9fc1eb52def6dc6 blob 62 92 5083444 3 3faa5832a9e087a5d4cf2b493c52f97eda478242
I would like to replace one or more of the white spaces in the above output with '___' in the same pipe. I have tried:
$objects = git -C "$localRepoPath" verify-pack -v (Get-ChildItem "$PackFiles\pack-*.idx")`
| Select-String -Pattern "blob"`
| % { $_.Line -replace '\s+', '___' }`
| Select -First 5
# Output each line
$objects | % {
$_.Line
}
But the output is empty. How do I accomplish that?

Delete duplicate string with PowerShell

I have got text file:
1 2 4 5 6 7
1 3 5 6 7 8
1 2 3 4 5 6
1 2 4 5 6 7
Here first and last line are simmilar. I have a lot of files that have double lines. I need to delete all dublicate.
All these seem really complicated. It is as simple as:
gc $filename | sort | get-unique > $output
Using actual file names instead of variables:
gc test.txt| sort | get-unique > unique.txt
To get unique lines:
PS > Get-Content test.txt | Select-Object -Unique
1 2 4 5 6 7
1 3 5 6 7 8
1 2 3 4 5 6
To remove the duplicate
PS > Get-Content test.txt | group -noelement | `
where {$_.count -eq 1} | select -expand name
1 3 5 6 7 8
1 2 3 4 5 6
If order is not important:
Get-Content test.txt | Sort-Object -Unique | Set-Content test-1.txt
If order is important:
$set = #{}
Get-Content test.txt | %{
if (!$set.Contains($_)) {
$set.Add($_, $null)
$_
}
} | Set-Content test-2.txt
Try something like this:
$a = #{} # declare an arraylist type
gc .\mytextfile.txt | % { if (!$a.Contains($_)) { $a.add($_)}} | out-null
$a #now contains no duplicate lines
To set the content of $a to mytextfile.txt:
$a | out-file .\mytextfile.txt
$file = "C:\temp\filename.txt"
(gc $file | Group-Object | %{$_.group | select -First 1}) | Set-Content $file
The source file now contains only unique lines
The already posted options did not work for me for some reason