Reputation: 368
I have a text file with the following:
acl Safe_ports port 443
acl Safe_ports port 22
acl AzureDomains dstdomain .microsoft.com
acl AzureDomains dstdomain .azure.com
I want to be able to parse through this text file to get the ports and dstdomains into an array to be fed into a command in this format "$val1,$val2,$val3"
or an array of comma delimited values of $ports
or $urls
as needed.
Example - $NetRule1 = New-AzFirewallNetworkRule -Name $name -Protocol TCP -SourceAddress * -DestinationAddress * -DestinationPort "$val1,$val2,$val3"
or "$ports"
.
Currently, it is looping through my command but my current implementation overrides the previous value which is not the goal.
Sample:
$lines = Get-Content $file | Where-Object { $_ -notmatch '^\s+$' }
foreach ($line in $lines) {
$fields = $line -split '\s+'
$rulename = $fields[1]
$acltype = $fields[2]
$rules = $fields[3..4]
#$app = $field[4]
#$hosts = $fields[1..3]
foreach ($rule in $rules) {
if ($acltype -match "port") {
$port = $rule
}
elseif ($acltype -match "dstdomain") {
$url = $rule
}
}
}
I welcome a more effective way of doing this
Upvotes: 0
Views: 2153
Reputation: 17492
For import with csv (given into previous comment) :
#importation data
$Content=import-csv "c:\temp\file.csv" -d ","
#selection columns
$Ports=$Content | where ACLType -eq 'port'
$Urls=$Content | where ACLType -eq 'dstdomain'
#format result
$Ports.Rule -join ","
$Urls.Rule -join ","
Upvotes: 1
Reputation: 17492
$ports=@()
$urls=@()
Get-Content "c:\temp\test.txt" | Where { $_ -like '* port *' -or $_ -like '* dstdomain *' } | %{
$Split=$_ -split ' ', 4
if ($_ -like '* port *')
{
$ports+=$Split[3]
}
else
{
$urls+=$Split[3]
}
}
$ports -join ","
$urls -join ","
Upvotes: 0
Reputation: 25031
If we stick with your original approach, we can use one foreach
loop and output custom objects with the data you require. From the output, we can manipulate the text.
$lines = Get-Content $file | Where-Object { $_ -notmatch '^\s*$' }
$out = foreach ($line in $lines) {
$fields = $line -split '\s+'
[pscustomobject]@{
'RuleName' = $fields[1]
'ACLType' = $fields[2]
'Rule' = $fields[3]
}
}
$ports = $out.where{$_.ACLType -eq "port"}.Rule
$urls = $out.where{$_.ACLType -eq "dstdomain"}.Rule
There is no need to create a comma-separated string since your command is expecting an array on the -DestinationPort
parameter. You can see the additional approach below for a simpler way to just find text elements and join them as a single string.
Alternative Approach:
You can use Select-String
to find your text. Then use the -join
operator to create your comma-separated string.
$urls = (Select-String $file -Pattern "(?<=dstdomain\s+)\S+").Matches.Value -join ","
$ports = (Select-String $file -Pattern "(?<=port\s+)\d+").Matches.Value -join ","
Explanation:
Select-String
uses the -Pattern
parameter by default to perform a regex match. It returns a MatchInfo
object. In our case, this will be an array of MatchInfo
objects. Accessing the .Matches.Value
property outputs the matched string only.
(?<=)
is the positive lookbehind assertion for regex. In both commands, it is performed to look behind the current character for strings dstdomain
and port
and any white space that may follow them. \d+
matches consecutive digits. \S+
matches consecutive non-white space.
The resulting arrays are joined as comma-separated strings using the -join
operator.
You could technically do all of this with one Select-String
. It will likely add coding complexity to separate the combined data though. Two commands just appears simpler to me.
Upvotes: 1