Need to convert txt file to CSV (with headers) using PowerShell - powershell

Can we convert below txt file to CSV format added at the end?
Text file:
IP Address: 192.168.1.1
Hostname: 01-any1TEST
Event Message: Ping
Alert Status: Down at least 3 min
Event Time: 17:25:14
Alert Type: :Windows 2012 Server
-------------------------------------------------------------------------------------
IP Address: 192.168.1.2
Hostname: 02-any2TEST
Event Message: Ping
Alert Status: Down at least 4 min
Event Time: 17:25:40
Alert Type: :Unix Server
-------------------------------------------------------------------------------------
IP Address: 192.168.1.3
Hostname: 03-any3TEST
Event Message: Ping
Alert Status: Down at least 3 min
Event Time: 17:26:21
Alert Type: :windows host
-------------------------------------------------------------------------------------
CSV file output required as below:
'IP Address','Hostname','Event Message','Alert Status','Event Time','Alert Type'
'192.168.1.1','01-any1TEST','Ping','Down at least 3 min','17:26:21','Windows 2012 Server '
'192.168.1.2','02-any2TEST','Ping','Down at least 3 min','17:26:21','unix host '
'192.168.1.3','03-any3TEST','Ping','Down at least 3 min','17:26:21','windows host '

Here's one way you could do it:
$logFile = "logfile.txt"
$delimeterPattern = '^####'
$recordPattern = '^([^:]+): (.+)'
# how many lines in a record?
$recordLines = Select-String $delimeterPattern $logFile -List |
Select-Object -ExpandProperty LineNumber
$logContent = Get-Content $logFile
for ( $i = 0; $i -lt $logContent.Count; $i += $recordLines ) {
$output = New-Object PSObject
for ( $j = $i; $j -lt $i + $recordLines; $j++ ) {
$logContent[$j] | Select-String $recordPattern | ForEach-Object {
$output | Add-Member NoteProperty $_.Matches[0].Groups[1].Value $_.Matches[0].Groups[2].Value
}
}
$output
}
To write to a CSV file, put the above in a script and pipe to Export-Csv.

I hope this will solve your problem:
Function Convert2CSV()
{
param($logFile, $csvFile)
"'IP Address','Hostname','Event Message','Alert Status','Event Time','Alert Type'" | Out-File $csvFile
get-content $logFile -Delimiter "-------------------------------------------------------------------------------------" | &{ process{
$IsValidMatch=$_ -match "IP Address: (.*)\r\nHostname: (.*)\r\nEvent Message: (.*)\r\nAlert Status: (.*)\r\nEvent Time: (.*)\r\nAlert Type: (.*)\r\n"
if($IsValidMatch)
{
$nextLine="'$($matches[1])','$($matches[2])','$($matches[3])','$($matches[4])','$($matches[5])','$($matches[6])'" | Out-File $csvFile -Append
}
}}
}
Finally call the Convert2CSV function, and define your log file and output file as parameter:
Convert2CSV -logFile .\1.txt -csvFile 3.txt

$delimeterPattern = '^--'
$recordPattern = '^([^:]+): (.+)'
$logContent = Get-Content "logfile.txt"
# how many lines in a record?
$recordLines = ($logContent | Select-String $delimeterPattern |
Select-Object -First 1).LineNumber
for ( $i = 0; $i -lt $logContent.Count; $i += $recordLines ) {
$output = New-Object PSObject
for ( $j = $i; $j -lt $i + $recordLines; $j++ ) {
$logContent[$j] | Select-String $recordPattern | ForEach-Object {
$output | Add-Member NoteProperty $_.Matches[0].Groups[1].Value
$_.Matches[0].Groups[2].Value
}
}
$output
}
Updated seprator $delimeterPattern = '^--' to $delimeterPattern = '^####' .

Related

Find out Text data in CSV File Numeric Columns in Powershell

I am very new in powershell.
I am trying to validate my CSV file by finding out if there is any text value in my numeric fields. I can define with columns are numeric.
This is my source data like this
ColA ColB ColC ColD
23 23 ff 100
2.30E+01 34 2.40E+01 23
df 33 ss df
34 35 36 37
I need output something like this (only text values if found in any column)
ColA ColC ColD
2.30E+01 ff df
df 2.40E+01
ss
I have tried some code but not getting any results, get only some output like as under
System.Object[]
---------------
xxx fff' ddd 3.54E+03
...
This is what I was trying
#
cls
function Is-Numeric ($Value) {
return $Value -match "^[\d\.]+$"
}
$arrResult = #()
$arraycol = #()
$FileCol = #("ColA","ColB","ColC","ColD")
$dif_file_path = "C:\Users\$env:username\desktop\f2.csv"
#Importing CSVs
$dif_file = Import-Csv -Path $dif_file_path -Delimiter ","
############## Test Datatype (Is-Numeric)##########
foreach($col in $FileCol)
{
foreach ($line in $dif_file) {
$val = $line.$col
$isnum = Is-Numeric($val)
if ($isnum -eq $false) {
$arrResult += $line.$col
$arraycol += $col
}
}
}
[pscustomobject]#{$arraycol = "$arrResult"}| out-file "C:\Users\$env:username\Desktop\Errors1.csv"
####################
can someone guide me right direction?
Thanks
You can try something like this,
function Is-Numeric ($Value) {
return $Value -match "^[\d\.]+$"
}
$dif_file_path = "C:\Users\$env:username\desktop\f2.csv"
#Importing CSVs
$dif_file = Import-Csv -Path $dif_file_path -Delimiter ","
#$columns = $dif_file | Get-member -MemberType 'NoteProperty' | Select-Object -ExpandProperty 'Name'
# Use this to specify certain columns
$columns = "ColB", "ColC", "ColD"
foreach($row in $dif_file) {
foreach ($col in $columns) {
if ($col -in $columns) {
if (!(Is-Numeric $row.$col)) {
$row.$col = ""
}
}
}
}
$dif_file | Export-Csv C:\temp\formatted.txt
Look up name of columns as you go
Look up values of each col in each row and if it is not numeric, change to ""
Exported updated file.
I think not displaying columns that have no data creates the challenge here. You can do the following:
$csv = Import-Csv "C:\Users\$env:username\desktop\f2.csv"
$finalprops = [collections.generic.list[string]]#()
$out = foreach ($line in $csv) {
$props = $line.psobject.properties | Where {$_.Value -notmatch '^[\d\.]+$'} |
Select-Object -Expand Name
$props | Where {$_ -notin $finalprops} | Foreach-Object { $finalprops.add($_) }
if ($props) {
$line | Select $props
}
$out | Select-Object ($finalprops | Sort)
Given the nature of Format-Table or tabular output, you only see the properties of the first object in the collection. So if object1 has ColA only, but object2 has ColA and ColB, you only see ColA.
The output order you want is quite different than the input CSV; you're tracking bad text data not by first occurrence, but by column order, which requires some extra steps.
test.csv file contents:
ColA,ColB,ColC,ColD
23,23,ff,100
2.30E+01,34,2.40E+01,23
df,33,ss,df
34,35,36,37
Sample code tested to meet your description:
$csvIn = Import-Csv "$PSScriptRoot\test.csv";
# create working data set with headers in same order as input file
$data = [ordered]#{};
$csvIn[0].PSObject.Properties | foreach {
$data.Add($_.Name, (New-Object System.Collections.ArrayList));
};
# add fields with text data
$csvIn | foreach {
$_.PSObject.Properties | foreach {
if ($_.Value -notmatch '^-?[\d\.]+$') {
$null = $data[$_.Name].Add($_.Value);
}
}
}
$removes = #(); # remove `good` columns with numeric data
$rowCount = 0; # column with most bad values
$data.GetEnumerator() | foreach {
$badCount = $_.Value.Count;
if ($badCount -eq 0) { $removes += $_.Key; }
if ($badCount -gt $rowCount) { $rowCount = $badCount; }
}
$removes | foreach { $data.Remove($_); }
0..($rowCount - 1) | foreach {
$h = [ordered]#{};
foreach ($key in $data.Keys) {
$h.Add($key, $data[$key][$_]);
}
[PSCustomObject]$h;
} |
Export-Csv -NoTypeInformation -Path "$PSScriptRoot\text-data.csv";
output file contents:
"ColA","ColC","ColD"
"2.30E+01","ff","df"
"df","2.40E+01",
,"ss",
#Jawad, Finally I have tried
function Is-Numeric ($Value) {
return $Value -match "^[\d\.]+$"
}
$arrResult = #()
$columns = "ColA","ColB","ColC","ColD"
$dif_file_path = "C:\Users\$env:username\desktop\f1.csv"
$dif_file = Import-Csv -Path $dif_file_path -Delimiter "," |select $columns
$columns = $dif_file | Get-member -MemberType 'NoteProperty' | Select-Object -ExpandProperty 'Name'
foreach($row in $dif_file) {
foreach ($col in $columns) {
$val = $row.$col
$isnum = Is-Numeric($val)
if ($isnum -eq $false) {
$arrResult += $col+ " " +$row.$col
}}}
$arrResult | out-file "C:\Users\$env:username\desktop\Errordata.csv"
I get correct result in my out file, order is very ambiguous like
ColA ss
ColB 5.74E+03
ColA ss
ColC rrr
ColB 3.54E+03
ColD ss
ColB 8.31E+03
ColD cc
any idea to get proper format? thanks
Note: with your suggested code, I get complete source file with all data , not the specific error data.

How to set a variable to a column with no header in a tab delimited text file

Barcode1 Plate # 12/29/2017 07:35:56 EST
A 1 4 5 6
A 1 4 5 6
A 1 4 5 6
A 1 4 5 6
A 1 4 5 6
A 1 4 5 6
A 1 4 5 6
Above is an example of a tab delimited text file. I need to get the data from the column with no header; namely, the columns at the end and I don't know how to identify it. I am trying to swap columns and output a text file. The source data file format is the same every time.
This is part of what I have:
$swapColumns = #{
column1 = #{
name = "date-header"
instance = 1
}
column2 = #{
name = "Blank"
instance = 1
}
}
$formats = #(
'XR-{0:yyyyMMdd}-01.txt'
)
$date = [datetime]::now
$ErrorActionPreference = 'Stop'
function Get-HeaderIndex {
param(
[System.Collections.Generic.List[string]]$Source,
[string]$Header,
[uint16]$Instance
)
$index = 0;
for ($i = 0; $i -lt $Instance; $i++) {
$index = $Source.IndexOf($Header, $index, ($Source.Count - $index))
if (($index -eq -1) -or (($i + 1) -eq $Instance)) {
break
}
$index = $index + 1
}
if ($index -eq -1) { throw "index not found" }
return $index
}
#grabs the first item in folder matching UCX-*.txt
$fileDetails = Get-ChildItem $PSScriptRoot\UCX-*.txt | select -First 1
#gets the file contents
$file = Get-Content $fileDetails
#break up script in sections that look like '======section======'
#and store the section name and line number it starts on
$sections = #()
for ($i = 0; $i -lt $file.Count; $i++) {
if ($file[$i] -match '^=+(\w+)=+$') {
$section = $Matches[1]
$sections += [pscustomobject]#{line = $i; header = $section}
}
}
#get the data section
$dataSection = $sections | ? {$_.header -eq 'data'}
#get the section following data
$nextSection = $sections | ? {$_.line -gt $dataSection.line} | sort
-Property line | select -First 1
#get data column headers
$dataHeaders = New-Object System.Collections.Generic.List[string]
$file[$dataSection.line + 1].split("`t") | % {
[datetime]$headerDateValue = [datetime]::MinValue
$headerIsDate = [datetime]::TryParse($_.Replace('EST','').Trim(),
[ref] $headerDateValue)
if ($headerIsDate) {
$dataHeaders.Add('date-header')
}
else {
$dataHeaders.Add($_)
}
}
#get index of columns defined in $swapColumns
$column1 = Get-HeaderIndex -Source $dataHeaders -Header
$swapColumns.column1.name -Instance $swapColumns.column1.instance
$column2 = Get-HeaderIndex -Source $dataHeaders -Header
swapColumns.column2.name -Instance $swapColumns.column2.instance
#iterate over each row in data section, swap data from column1/column2
for ($i = $dataSection.line + 2; $i -lt $nextSection.line - 1; $i++) {
$line = $file[$i]
$parts = $line.split("`t")
$tmp1 = $parts[$column1]
$parts[$column1] = $parts[$column2]
$parts[$column2] = $tmp1
$file[$i] = $parts -join "`t"
}
#write new file contents to files with names defined in $formats
$formats | % {
$file | Out-File ($_ -f $date) -Force
}
If you know what your file format is going to be then forget whatever the current header is and assume when we convert the file to a CSV object.
It looks like you need to parse the date of out the header which should be trivial. Grab it from $fileheader however you would like.
$wholeFile = Get-Content C:\temp\test.txt
$fileHeader = $wholeFile[0] -split "`t"
$newHeader = "Barcode1", "Plate #", "Date", "Plumbus", "Dinglebop"
$wholeFile |Select-Object -Skip 1 | ConvertFrom-Csv -Delimiter "`t" -Header $newHeader
If the columns length is always the same, there's another option, specify manually the width of the columns, See example:
$content = Get-Content C:\temp.tsv
$columns = 13, 24, 35 | Sort -Descending
$Delimiter = ','
$Results = $content | % {
$line = $_
$columns | % {
$line = $line.Insert($_, $Delimiter)
}
$line
} |
ConvertFrom-Csv -Delimiter $Delimiter
Results:
Barcode1 Plate # H1 12/29/2017 07:35:56 EST
--------- ----------- -- -----------------------
A 1 4 5
A 1 4 5
A 1 4 5
A 1 4 5
A 1 4 5
A 1 4 5
A 1 4 5
Then you can easily get the data you need:
$Results[0].H1
4
[This answer doesn't solve the OP's problem after clarifying the exact requirements, but may be of general interest to some, given the question's generic title.]
If the file is really tab-delimited, you can use Import-Csv -Delimiter "`t" to read it, in which case PowerShell will autogenerate header names as H<n> if they're missing, where <n> is a sequence number starting with 1.
Caveat: This doesn't work if the unnamed column is the last one, because - inexplicably - Import-Csv then ignores the entire column (more generally, any run of trailing delimiters).
Import-Csv -Delimiter "`t" file.tsv | Select-Object -ExpandProperty H1

Pivot/transform a PSObject which contains a list of values?

Have an psobject which is assigned with the following values,
echo "A|B|C|X,A|B|C|Y,A|B|C|Z,D|E|F|X,D|E|F|Y,D|E|F|Z
1,3,5,2,3,7" > 'c:\temp\test.csv'
$d = Import-Csv 'c:\temp\test.csv'
$d | select -first 1
A|B|C|X : 1
A|B|C|Y : 3
A|B|C|Z : 5
D|E|F|X : 2
D|E|F|Y : 3
D|E|F|Z : 7
....
I want it be tranformed to arrays,
A,B,C,1,3,5
D,E,F,2,3,7
....
- - - - - -
X Y Z
Is it a concise way to pivot the psobject? The converting function head can be
function Convert($datarow, [string[]]$pivotCols) { ... }
Convert($d, 'X','Y','Z')
Actually it's one of those rare situations where $d being a PSObject doesn't give you any benefits. Here's an example of how you could achieve what you want, although I'm not certain it's the most concise way:
# Transforming input.
$sInput = "A|B|C|X,A|B|C|Y,A|B|C|Z,D|E|F|X,D|E|F|Y,D|E|F|Z
1,3,5,2,3,7"
$sRawNames, $sRawValues = $sInput -split ([System.Environment]::NewLine)
$cRawNames = $sRawNames -split ','
$cRawValues = $sRawValues -split ','
# Grouping fields by name pattern.
$sGroupingPattern = '\|[XYZ]'
$htGrouped = [Ordered]#{}
for ($i = 0; $i -lt $cNames.Count; $i++) {
$sName = $cRawNames[$i] -replace $sGroupingPattern
try {
$htGrouped.Add($sName, #($cRawValues[$i]))
}
catch [ArgumentException] {
$htGrouped[$sName] += $cRawValues[$i]
}
}
# Formatting output.
$cOutput = #()
$htGrouped.GetEnumerator() | ForEach-Object {
$cValues = ($_.Name -split '\|') + $_.Value
$oValues = New-Object -TypeName PSObject
for ($i = 0; $i -lt $cValues.Count; $i++) {
$oValues | Add-Member -MemberType "NoteProperty" -Name $i -Value $cValues[$i]
}
$cOutput += $oValues
}
$cOutput | Format-Table

Check for DNS record using PowerShell 2.0

What could be the best way to resolve a computer name apart from using:
[System.Net.DNS]::GetHostByName('MachineName').HostName
I dont want to import any specific DNS Modules.
You can try the GetHostEntry method:
[Net.DNS]::GetHostEntry("MachineName")
Another way would be to ping it using Test-Connection cmdlet, see this tip
I was in a case where I had to query a specific DNS server, which is not possible directly with .net / powershell. So I ended up with using the good old nslookup :
$client="10.110.10.10"
$ns="10.20.1.10"
(nslookup $client $ns |sls name).toString().split(":")[1].trim()
The following 2 ways to resolve IP's to DNS addresses are the only ones.
It's how you use it that counts.
[Net.DNS]::GetHostEntry("MachineName")
[System.Net.DNS]::GetHostByName('MachineName').HostName
Like I said, It's how you use them.
I have written a script for doing just this.
It takes a list of IP addresses and resolves there DNS.
Later in the script it converts the output to an excel sheet, showing you the results.
Based upon filters you can set the layout.
Now I know not all IP's will be resolved with these methods, that's why I included a function in my script that filters out unresolved IP's and places them to the bottom of the excel sheet.
(Giving every IP a direct link to who.is/whois/ipadress
Here's the script, íf you are interested.
#Get current date
$Date = date -format yyyy-MM-dd
$Company = "Company"
$Company2 = "Company2"
########################
#Define all Paths.
$Path = "C:\inetpub\wwwroot\BlockedIP" #This is where your file's will be saved.
md "$Path\HTML\$Date" -Force |Out-Null
$path2 = "$Path\HTML\$Date"
$PathWeb = "/ResolvedIp/HTML/$Date"
########################
#Define File's used or created in this script.
$File = "$Path\IP-$Date.txt"
$FileHtml = "$Path2\IP-$Date.htm"
$FileXML = "$Path\IP-$Date.xlsx"
$FileHTMLWeb = "$PathWeb\IP-$date.htm"
######################################
#Define error actions.
$erroractionpreference = "SilentlyContinue"
###########################################
#Since the script used COM objects it will need the following 2 folders:
#(32Bit)
MD "C:\Windows\System32\config\systemprofile\Dektop" -force
MD "C:\Windows\System32\config\systemprofile\AppData\Local\Microsoft\Windows\Temporary Internet" -force
#(64Bit)
MD "C:\Windows\SysWOW64\config\systemprofile\Desktop" -force
MD "C:\Windows\SysWOW64\config\systemprofile\AppData\Local\Microsoft\Windows\Temporary Internet" -force
#Once successfull the script will run without a problem if scheduled.
cls
(gc $File) | ? {$_.trim() -ne "" } | set-content $File
$IPCount = (gc $File)
$IPCount = $IPCount.count
write "$IPCount unique IP addresses detected."
#Define error actions.
$erroractionpreference = "SilentlyContinue"
#Get content from given IP list.
$colComputers = #(gc $File | sort |Select -unique)
$SourceCount = $colComputers.Count
write "$SourceCount IP's detected."
Function Set-KnownIPs{
Param([Object]$DNSLookupObject)
Switch($DNSLookupObject){
{$_.Source -Match "(108.162.254|141.101.(?:104|105)|199.27.128|173.245(?:53|52|51))"}{$_.HostName = "CloudFlare, Inc."}
{$_.Source -Match "(64.18.[0-18])"}{$_.HostName = "Google, Inc."}
{$_.Source -Match "(192.168|127.0.0)"}{$_.HostName = "Internal Infrastructure"}
}
$DNSLookupObject
}
#Get DNS Results
$Progress=1
$DNSResults = $colComputers | %{
Write-Progress -Activity "Creating a usable 'Blocked IP' list ($Progress/$sourcecount)" -PercentComplete ($Progress/$sourceCount*100) -Status "Please stand by"
try {
($dnsresult = [System.Net.DNS]::GetHostEntry($_))
}
catch {
$dnsresult = "Fail"
}
Set-KnownIPs -DNSLookupObject ([PSCustomObject][Ordered]#{
Source=$_.ToUpper()
HostName=$(if(!([string]::IsNullOrEmpty($dnsresult.HostName))){$dnsresult.HostName})
IPAddress=$(if(!([string]::IsNullOrEmpty($dnsresult.AddressList))){$dnsresult.AddressList[0].ToString()})
})
$Progress++
}
$Keywords = #("Google","Cloudflare","Cloud","Ping",
"Easy-Voyage","McAfee","Pingdom","Panopta","Scoot","Uniglobe",
"Internal")
$Filter = "($(($Keywords|%{[RegEx]::Escape($_)}) -join "|"))"
$DNSLookupFailed = $DNSResults |
?{[string]::IsNullOrEmpty($_.HostName) -and !($_ -match $filter)}
$DNSWithKeyword = $DNSResults |
?{$_ -match $Filter}
$DNSNoKeyword = $DNSResults |
?{!($_.HostName -match $Filter) -and !([string]::IsNullOrEmpty($_.IPAddress))}
#$count = ($DNSResults|?{$_ -match $filter}).count
$count = $SourceCount
#####################
#start Excel.
$a = New-Object -comobject Excel.Application
# set interactive to false so nothing from excel is shown.
$a.DisplayAlerts = $False
$a.ScreenUpdating = $True
$a.Visible = $True
$a.UserControl = $True
$a.Interactive = $True
###########################
#Create sheets in Excel.
$b = $a.Workbooks.Add()
$c = $b.Worksheets.Item(1)
$c.Activate() | Out-Null
#Create a Title for the first worksheet and adjust the font
$c.Cells.Item(1,1)= "Blocked IP's $Date"
$c.Cells.Item(1,1).Font.ColorIndex = 55
$c.Cells.Item(1,1).Font.Color = 8210719
$c.Cells.Item((3+$DNSWithKeyword.Count+1),1) = "IP's not in whitelist"
$c.Cells.Item((3+$DNSWithKeyword.Count+1),1).Font.ColorIndex = 55
$c.Cells.Item((3+$DNSWithKeyword.Count+1),1).Font.Color = 8210719
$c.Cells.Item((3+$DNSWithKeyword.Count+$DNSNoKeyword.Count+3),1)= "IP's without DNS return"
$c.Cells.Item((3+$DNSWithKeyword.Count+$DNSNoKeyword.Count+3),1).Font.ColorIndex = 55
$c.Cells.Item((3+$DNSWithKeyword.Count+$DNSNoKeyword.Count+3),1).Font.Color = 8210719
#######################################
$range = $c.Range("a1","e1")
$range.Style = 'Title'
$range.Select()
$range.MergeCells = $true
$range.VerticalAlignment = -4108
################################
$Linkedin = "https://www.linkedin.com/profile/view?id=96981180" #Look me up! :D
#Define row to be used for linkedin link.
$CounterRow = $Count+5
######################
#Define subjects.
$c.Name = "Blocked IP's ($Date)"
$c.Cells.Item(2,1) = "Given IP"
$c.Cells.Item(2,2) = "Resolved DNS"
$c.Cells.Item(2,3) = "Returned IP"
$c.Cells.Item(2,5) = "$Company"
$c.Cells.Item((3+$DNSWithKeyword.Count+$DNSNoKeyword.Count+$DNSLookupFailed.Count+5),1) = "Created by"
########################################
$link = "http://www.$Company"
$link2 = "$Linkedin"
$r = $c.Range("E2")
[void]$c.Hyperlinks.Add($r, $link)
$r = $c.Range("A$(3+$DNSWithKeyword.Count+$DNSNoKeyword.Count+$DNSLookupFailed.Count+5)")
[void]$c.Hyperlinks.Add($r, $link2)
###################################
#Define cell formatting from subjects.
$c.Range("A2:E2").Interior.ColorIndex = 6
$c.Range("A2:E2").font.size = 13
$c.Range("A2:E2").Font.ColorIndex = 1
$c.Range("A2:E2").Font.Bold = $True
###################################
#Define the usedrange, excluding header and footer rows
$KeyRange = $c.Range("A3:c$(3+$DNSWithKeyword.Count)")
$NoKeyRange = $c.Range("A$(3+$DNSWithKeyword.Count+2):c$(3+$DNSWithKeyword.Count+$DNSNoKeyword.Count+2)")
$NoDNSRange = $c.Range("A$(3+$DNSWithKeyword.Count+$DNSNoKeyword.Count+4):c$(3+$DNSWithKeyword.Count+$DNSNoKeyword.Count+$DNSLookupFailed.Count+4)")
$SheetRange = $c.Range("A3:e$(4+$DNSWithKeyword.Count+$DNSNoKeyword.Count+$DNSLookupFailed.Count+4)")
$Investigate = $c.Range("c$(3+$DNSWithKeyword.Count+$DNSNoKeyword.Count+4):c$(3+$DNSWithKeyword.Count+$DNSNoKeyword.Count+$DNSLookupFailed.Count+4)")
################################
#Set background color for the IP list.
$SheetRange.interior.colorindex = 6
$KeyRange.interior.colorindex = 4
$NoKeyRange.interior.colorindex = 15
$NoDNSRange.interior.colorindex = 8
####################################
#Populate data into spreadsheet
$DNSWithKeyword | Select Source, HostName, IPAddress | Sort HostName -Descending |
ConvertTo-Csv -Delimiter "`t" -NoTypeInformation |
Select -Skip 1 | Clip
$c.Paste($KeyRange,$false)
$DNSNoKeyword | Select Source, HostName, IPAddress | Sort HostName -Descending |
ConvertTo-Csv -Delimiter "`t" -NoTypeInformation |
Select -Skip 1 | Clip
$c.Paste($NoKeyRange,$false)
$DNSLookupFailed | Select Source, HostName, IPAddress | sort Source -Descending|
ConvertTo-Csv -Delimiter "`t" -NoTypeInformation |
Select -Skip 1 | Clip
$c.Paste($NoDNSRange,$false)
############################
ForEach($Cell in $Investigate){
If([String]::IsNullOrWhitespace($Cell.value2)){
$Cell.Item($_) = "N/A"
[void]$cell.Hyperlinks.Add($Cell)
}
}
###########################################################################
#Define borders here.
$xlOpenXMLWorkbook = 51
$xlAutomatic=-4105
$xlBottom = -4107
$xlCenter = -4108
$xlRight = -4152
$xlContext = -5002
$xlContinuous=1
$xlDiagonalDown=5
$xlDiagonalUp=6
$xlEdgeBottom=9
$xlEdgeLeft=7
$xlEdgeRight=10
$xlEdgeTop=8
$xlInsideHorizontal=12
$xlInsideVertical=11
$xlNone=-4142
$xlThin=2
#########
$selection = $c.range("A2:C$(1+$DNSResults.Count-9)")
$selection.select() |out-null
$selection.HorizontalAlignment = $xlRight
$selection.VerticalAlignment = $xlBottom
$selection.WrapText = $false
$selection.Orientation = 0
$selection.AddIndent = $false
$selection.IndentLevel = 0
$selection.ShrinkToFit = $false
$selection.ReadingOrder = $xlContext
$selection.MergeCells = $false
$selection.Borders.Item($xlInsideHorizontal).Weight = $xlThin
#############################################################
#Define the usedrange for autofitting.
$d = $c.UsedRange
#################
#Make everything fit in it's cell.
$d.EntireColumn.AutoFit() | Out-Null
####################################
$c.usedrange | Where{$_.Value2 -match "(\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b)"} |
ForEach{$IPLink = "http://who.is/whois-ip/ip-address/$($Matches[1])";[void]$c.Hyperlinks.Add($_, $IPLink)}
#Define html code for Excel save to .htm.
$xlExcelHTML = 44
#################
#Save final result as an .xlsx file.
$b.SaveAs("$FileXML")
#####################
#Save final result as a .htm file
$b.SaveAs("$FileHTML",$xlExcelHTML)
###################################
In powershell 5.1 you can use
Resolve-DnsName

Format display in powershell

I have a csv file with the following information:
OS Name: Microsoft© Windows Server© 2008 Standard
OS Version: 6.0.6002 Service Pack 2 Build 6002
System Manufacturer: IBM
System Model: IBM 3850 M2 / x3950 M2 -[7233Z1H]-
I need to use powrshell to read and format the display.. My existing code is this:
$Array = #()
Get-Content <txtfilename> | foreach {
$Test = $_
$Title = $Test.split(":")[0]
$Content = $Test.split(":")[1]
$Obj = New-Object System.Object
$Obj | Add-Member -MemberType NoteProperty -value $Title -Name Title
$Obj | Add-Member -MemberType NoteProperty -value $Content -Name Value
$Array += $Obj
}
$Array | Select Title,Value | Export-Csv <csvfilename> -NoTypeInformation
It displays the information as follows listed:
Title Content
OS Name Microsoft? Windows Server? 2008 Standard
OS Version 6.0.6002 Service Pack 2 Build 6002
System Manufacturer IBM
System Model IBM 3850 M2 / x3950 M2 -[7233Z1H]-
I need the information displayed in a single line like this:
ServerName, OS Name , OS Version, System Manufacture, Sytem model,
TestServer1, Microsoft Windows, 6.0.6002 Service Pack 2, IBM, IBM 3850
Thanks
Here's a second answer for the more advanced case, where you don't know how many unique headers you have or what they're called. As long as they're consistently the same and in the same order, the following will work:
$filePath = "C:\users\chris\desktop\info.txt"
$headers = #()
[int]$headerCount = 0
$endUnique = $false
Get-Content $filePath | % {
$header = ($_.split(':')[0] -replace '\s+', ' ').Trim()
if (($headers -notcontains $header) -and (!$endUnique)){
$headers += $header
$headerCount += 1
}
else{
$endUnique = $true
}
}
$headerRow = ""
$headers | % {$headerRow += $_ + ","}
$headerRow = $headerRow.Substring(0,$headerRow.Length-1)
[int]$i = 1
$outString = ""
Get-Content $filePath | % {
$lineContent = ($_.split(':')[1] -replace '\s+', ' ').Trim()
if ($i -lt $headerCount){
$outstring += $linecontent + ','
$i += 1
}
else{
$outstring += $linecontent + "`r`n"
$i = 1
}
}
$outstring = $headerRow+ "`r`n"+$outstring
I'd like to see the other answers from more advanced PowerShell users.
First, just a quick correction. You say you have a CSV. It looks like you have a formatted text file and you want to make a CSV out of it.
Following that assumption, something like this should get you started. It assumes that the text document has either only those 4 items in it, or those 4 items are repeated multiple times - always in the same order, and without a space in between them. Reformatting text files is never fun without a bunch of examples of how they could look.
That being said, the following should get you started.
[int]$i = 1
$outString = ""
Get-Content C:\users\chris\desktop\info.txt | % {
#Take the line, remove the title, remove whitespaces from inside of the line and trim whitespaces from the outside.
$lineContent = ($_.split(':')[1] -replace '\s+', ' ').Trim()
#Chunk them together...
if ($i -lt 4){
$outstring += $linecontent + ','
$i += 1
}
#or insert a return, new line
else{
$outstring += $linecontent + "`r`n"
$i = 1
}
}
#Add a header row. Now $outstring is your CSV formatted text.
$outstring = "OSName,OSVersion,SystemMfg,SystemModel`r`n"+$outstring
$object = New-Object System.Object
Get-Content TestServer1-OSInfo.txt | % {
If($_.Contains(":")){
$Left = $_.split(":")[0].TrimStart().TrimEnd()
$Right = $_.split(":")[1].TrimStart().TrimEnd()
$object | Add-Member -type NoteProperty -name $Left -value $Right
}
}
$object | Export-Csv TestServer1-OSInfo.csv -NoTypeInformation