Powershell move output of loop into Array - powershell

It seems like a simple answer but for the life of me I cant figure it out. What I am trying to do is get a bunch of email addresses out of a text file and strip out the bit of the email past the # (e.g if the email address was adam#home.com I am interested in the adam bit).
The script below outputs the values that I want however I would like to have the output written into a array rather than to the console. What would be the best way of doing this?
Code below, thanks.
# Import the text file into a variable
$import = Get-Content c:\\temp\test.txt
# Variable to hold total number of emails
$totalEmails = $import.Count
#Variable to run loop
$start = 0
#Used as a separator to look at the first part of the email address
$separator = "#"
# Will increment by two to show the first part of the array in parts which holds the text before the #
$even = 0
# Username after #
$userName
#Strip out the text before the #
do {
$parts = $import.split($separator)
$even+=2
# This line here is whats not working, I would like to have the output of each echo written into the array $userName
$userName = echo $parts[$even]
$start++
} while ($totalEmails -gt $start)

Your email parsing doesn't make a whole lot of sense. Here's a one-liner for your question:
$Arr = #(Get-Content -Path 'C:\temp\test.txt') -replace '#.+'

Related

Powershell - Get partial name as Variable

First posting here, and I'm a beginner in Powershell (Or most script, in the matter of fact).
What a try to do here is to take a part of a name file, and use it later To download a file from our server with the same name.
$name = Get-childitem -Path "$env:USERPROFILE\AppData\Local\Microsoft\Outlook\*.ost" -name
$username = $name.Remove($name.IndexOf('#'))
Write-Output $Username
I only get the the file name without what I put between ${.}
Thanks for any help
Split the string on the # and grab only the first item from the resulting array:
$name = "FirstName.LastName#company.com - more text you don't care about.ost"
# String.Split() returns an array of strings, `[0]` gives us the first item in that array
$username = $name.Split('#')[0]
Alteratively, remove everything from the original string beginning at the first #:
$username = $name.Remove($name.IndexOf('#'))

Powershell Script needed to redact items in between separators in a row according to defined list

Hello and thanks for reading. It's my first post and really need some help. The hardest part is getting my question across in a way that people will understand. I will try my best.
I have some huge csv files (some in excess of 8 millions rows so Excel not an option really) where I need to modify the contents of the 3rd 'field' in each row according to sets of words defined in a reference file
So an example csv might be something like:
AB12|TEST|CAT DOG MOUSE|TEST1|TEST2|TEST3||TEST4
CD34|TEST|HORSE CART TRAIN|TEST1|TEST2|TEST3||TEST4
etc etc.
In my reference file I have a list eg:
CAT
HORSE CART
These are contained in a CSV
What I need is to modify the files so that the 3rd 'field' (everything after the 2nd'|' and before the 3rd '|' is compared to the reference list and modified to match. ie in the first line, everything after CAT would be deleted and in the second line, everything after HORSE CART would be deleted within this 3rd field. So the resultant file outputted would look like:
AB12|TEST|CAT|TEST1|TEST2|TEST3||TEST4
CD34|TEST|HORSE CART|TEST1|TEST2|TEST3||TEST4
I normally use F.A.R.T to modify large files, but this needs to be a bit more clever than FART is able to offer.
I really hope this makes sense to someone out there and appreciate any help you might offer.
So far I have been experimenting with this, but it's a long way off doing what I want:
cls
$content = ""
write-output "** Original String **"
write-output ""
$content = Get-Content "~\Desktop\Test\*.dat"
$content
$separator1 = " "
$separator2 = "|"
$parts = $content.split($separator1)
write-output ""
write-output "** Revised String **"
write-output ""
$part1 = echo $parts[0]
$part3 = $part2.split($separator2)
$part4 = $part3[1]
$revised = $part1, $part4 -join "|"
$revised
write-output ""
So in summary then: This is really a modified 'Find and Replace Text' function that concentrates on a single field in each line, looks for matching sets of words, then deletes everything in that field other than the matched words, which are defined in a separate csv file.
Ok, as comparing arrays in PowerShell doesn't support wild cards we have to do this the old fashioned (costly) way. Compare every field with every reference.
I've not provided an example of reading the file as that can be done in different ways with regards to speed or memory consumption (your choice).
Also, I've provided the reference as an array instead as a file input to keep the example to the point (and easily testable).
The output should then of course be done to a new file instead of written to the host.
$file = #"
F1|F2|F3|F4|F5|F6|F7|F8
AB12|TEST|CAT DOG MOUSE|TEST1|TEST2|TEST3||TEST4
CD34|TEST|HORSE CART TRAIN|TEST1|TEST2|TEST3||TEST4
CD34|TEST|HORSE CART|TEST1|TEST2|TEST3||TEST4
"#
$ref = #("CAT*","HORSE CART*")
$file.split("`n") | foreach {# line in file
$outline = $nul
$_.split('|') | foreach {# field in the line
$field = $_
$refhit = $false
$ref | foreach {# item in the ref array
if ($field -like $_) {# replace field with ref
$refhit = $true
$outline += $_.TrimEnd('*') + '|'
}# end match
}# end ref
if (!$refhit){#pass on the field as is
$outline += "$field|"
}
}#end field
# Output filtered line
write-host $outline.TrimEnd('|')
}#end line

How can I loop through each record of a text file to replace a string of characters

I have a large .txt file containing records where a date string in each record needs to be incremented by 2 days which will then update the field to the right of it which contains dashes --------- with that date. For example, a record contains the following record data:
1440149049845_20191121000000 11/22/2019 -------- 0.000 0.013
I am replacing the -------- dashes with 11/24/2019 (2 days added to the date 11/22/2019) so that it shows as:
1440149049845_20191121000000 11/22/2019 11/24/2019 0.000 0.013
I have the replace working on a single record but need to loop through the entire .txt file to update all of the records. Here is what I tried:
$inputRecords = get-content '\\10.12.7.13\vipsvr\Rancho\MRDF_Report\_Report.txt'
foreach ($line in $inputRecords)
{
$item -match '\d{2}/\d{2}/\d{4}'
$inputRecords -replace '-{2,}',([datetime]$matches.0).adddays(2).tostring('MM/dd/yyyy') -replace '\b0\.000\b','0.412'
}
I get an PS error stating: "Cannot convert null to type "System.DateTime"
I'm sorry but why are we using RegEx for something this simple?
I can see it if there are differently formatted lines in the file, you'd want to make sure you aren't manipulating unintended lines, but that's not indicated in the question. Even still, it doesn't seem like you need to match anything within the line itself. It seems like it's delimited on spaces which would make a simple split a lot easier.
Example:
$File = "C:\temp\Test.txt"
$Output =
ForEach( $Line in Get-Content $File)
{
$TmpArray = $Line.Split(' ')
$TmpArray[2] = (Get-Date $TmpArray[1]).AddDays(2).ToString('M/dd/yyyy')
$TmpArray -join ' '
}
The 3rd element in the array do the calculation and reassign the value...
Notice there's no use of the += operator which is very slow compared to simply assigning the output to a variable. I wouldn't make a thing out of it but considering we don't know how big the file is... Also the String format given before 'mm/dd/yyyy' will result in 00 for the month like for example '00/22/2019', so I changed that to 'M/dd/yyyy'
You can still add logic to skip unnecessary lines if it's needed...
You can send $Output to a file with something like $Output | Out-File <FilePath>
Or this can be converted to a single pipeline that outputs directly to a file using | ForEach{...} instead of ForEach(.. in ..) If the file is truly huge and holding $Output in memory is an issue this is a good alternative.
Let me know if that helps.
You mostly had the right idea, but here are a few suggested changes, but not exactly in this order:
Use a new file instead of trying to replace the old file.
Iterate a line at a time, replace the ------, write to the new file.
Use '-match' instead of '-replace', because as you will see below that you need to manipulate the capture more than a simple '-replace' allows.
Use [datetime]::parseexact instead of trying to just force cast the captured text.
[string[]]$inputRecords = get-content ".\linesource.txt"
[string]$outputRecords
foreach ($line in $inputRecords) {
[string]$newLine = ""
[regex]$logPattern = "^([\d_]+) ([\d/]+) (-+) (.*)$"
if ($line -match $logPattern) {
$origDate = [datetime]::parseexact($Matches[2], 'mm/dd/yyyy', $null)
$replacementDate = $origDate.adddays(2)
$newLine = $Matches[1]
$newLine += " " + $origDate.toString('mm/dd/yyyy')
$newLine += " " + $replacementDate.toString('mm/dd/yyyy')
$newLine += " " + $Matches[4]
} else {
$newLine = $line
}
$outputRecords += "$newLine`n"
}
$outputRecords.ToString()
Even if you don't use the whole solution, hopefully at least parts of it will be helpful to you.
Using the suggested code from adamt8 and Steven, I added to 2 echo statements to show what gets displayed in the variables $logpattern and $line since it is not recognizing the pattern of characters to be updated. This is what displays from the echo:
Options MatchTimeout RightToLeft
CalNOD01 1440151020208_20191205000000 12/06/2019 12/10/2019
None -00:00:00.0010000 False
CalNOD01 1440151020314_20191205000000 12/06/2019 --------
None -00:00:00.0010000 False
this is the rendered output:
CalNOD01 1440151020208_20191205000000 12/06/2019 12/10/2019
CalNOD01 1440151020314_20191205000000 12/06/2019 --------
This is the code that was used:
enter image description here

how to get 2 values out of a string

Im hoping someone can help me with where to start, I want to pull some data out of some larger data
My data looks like this:
IP-MIB::ipNetToMediaPhysAddress.13600001.10.4.48.1 = STRING: 36:b:7:0:41:31
IP-MIB::ipNetToMediaPhysAddress.13600001.10.4.49.21 = STRING: 3b:fa:a2:us:74:d9
IP-MIB::ipNetToMediaPhysAddress.13600001.10.3.50.22 = STRING: 3b:fa:a2:us:7b:f3
There is an IP Address on each line starting with 10. and the mac address which is on the end, thats what I want to get out.
Ive been googling and am not sure where to start/what to do.
Is Regex the way to go, or is there a better way, any examples would be appreciated.
Thanks in advance
here's one way to get that info ... [grin]
fake reading in a text file
you will most likely want to use Get-Content or some pre-existing collection.
iterate thru the collection
use a named-capture-group regex to match on the IP & MAC
create a PSCustomObject from the match data
you can get them from the $Matches automatic variable.
send the current object out to be collected by the $Results variable
display that collection
here's the code ...
# fake reading in a text file
# in real life, use Get-Content
$InStuff = #'
IP-MIB::ipNetToMediaPhysAddress.13600001.10.4.48.1 = STRING: 36:b:7:0:41:31
IP-MIB::ipNetToMediaPhysAddress.13600001.10.4.49.21 = STRING: 3b:fa:a2:us:74:d9
IP-MIB::ipNetToMediaPhysAddress.13600001.10.3.50.22 = STRING: 3b:fa:a2:us:7b:f3
'# -split [environment]::NewLine
$Results = foreach ($IS_Item in $InStuff)
{
$Null = $IS_Item -match '\.\d{8}\.(?<IPv4>.+) = .+: (?<MacAddress>.+)$'
[PSCustomObject]#{
IPv4 = $Matches.IPv4
MacAddress = $Matches.MacAddress
}
}
$Results
you can use Export-CSV to send that to a nicely structured CSV file.

Powershell to read some strings from each line

I have a requirement like:
Have a text file containing the following in the following pattern
172.26.xxy.zxy:Administrator:Password
172.26.xxy.yyx:Administrator:Password
172.26.xxy.yyy:Administrator:Password
172.26.xxy.yxy:Administrator:Password
I need my powershell script to read each word and use that word whereever required. For example,
foreach(something)
{
I want the IP's(172.26.---.---) to read and store the value as a variable.
I want to store the two words after **:** in seperate variables.
}
How can this be done? I know to read an entire file or get some specific string. But I need the same to be done on each line.Any help would be really appreciated.
Something like this? You can just split on the : and then store your variables based on the index
$contents = Get-Content C:\your\file.txt
foreach($line in $contents) {
$s = $line -split ':'
$ip = $s[0]
$user = $s[1]
$pass = $s[2]
write-host $ip $user $pass
}
minor edit: "t" missing in content.
You can write a regular expression to replace to remove the parts you do not need
$ip_address= '172.26.xxy.zxy:Administrator:Password' -replace '^(.+):(.+):(.+)$','$1'
$user= '172.26.xxy.zxy:Administrator:Password' -replace '^(.+):(.+):(.+)$','$2'
$pwd= '172.26.xxy.zxy:Administrator:Password' -replace '^(.+):(.+):(.+)$','$3'
I think the more generic and pure Powershell way would be something like this:
Select-String "(.*):(.*):(.*)" c:\file.txt |
Select #{Name="IP"; Expression = {$_.Matches.Groups[1]}},
#{Name="User"; Expression = {$_.Matches.Groups[2]}},
#{Name="Password"; Expression = {$_.Matches.Groups[3]}}
The Output would be then an array of objects each having three properties IP, User and Password. So you can now use them for your purposes, or just add more commands at the end of the pipe.