Я новичок в программировании, и большая часть моего опыта связана с Python. Я работаю над простым сценарием PowerShell, который запускает Test-NetConnection по IP-адресу и портам в CSV-файле.
Каждый IP необходимо протестировать с каждым портом.
На данный момент у меня есть следующее: я не уверен, нужно ли мне создавать новый список для каждой комбинации IP/порта, а затем запускать для них foreach:
$csv_path = Read-Host -Prompt "Enter file path"
$csv = Import-Csv -Path "$csv_path"
foreach($item in $csv){
"{0} = {1}" -f $item.IP,$item.Port
Test-NetConnection -ComputerName "$item.IP" -Port "$item.Port" -InformationLevel Detailed
}
🤔 А знаете ли вы, что...
С помощью PowerShell можно аудитить и мониторить действия пользователей в системе.
Каждый IP необходимо протестировать с каждым портом.
Итак, вы проверяете порты 22, 25 и 80 для всех четырех IP-адресов? Всего 12 проверок на основе выборочных данных?
Данные CSV должны работать не так, но ладно, мы все равно можем это сделать.
$csv_path = Read-Host -Prompt "Enter file path"
$csv = Import-Csv -Path $csv_path
foreach($itemIP in $csv | ?{$_.IP.Length -gt 0}) {
foreach($itemPort in $csv | ?{$_.Port.Length -gt 0}) {
"$($itemIP.IP) = $($itemPort.Port)"
Test-NetConnection -ComputerName "$($itemIP.IP)" -Port "$($itemPort.Port)" -InformationLevel Detailed
}
}
В PowerShell есть удобная функция Перечисление доступа к участникам, которую вы можете использовать здесь.
Короче говоря, если вы получаете доступ к свойству или методу объекта массива (например, вашей переменной $csv
), он вызовет это свойство или метод для всех элементов массива и вернет новый массив со всеми результатами в нем.
Например, с этими тестовыми данными:
PS> $csv = @"
IP, Port
1.1.1.1, 22
1.1.1.2, 25
1.1.1.3, 80
1.1.1.4,
"@ | ConvertFrom-Csv
если вы вызовете $csv.IP
, вы получите массив всех свойств IP:
PS> $csv.IP
1.1.1.1
1.1.1.2
1.1.1.3
1.1.1.4
и то же самое для $csv.Port
:
PS> $csv.Port
22
25
80
(обратите внимание, что вывод «Порт» содержит 4 элемента — в четвертом индексе есть непечатаемый $null
)
Мы можем использовать это для выполнения вложенного цикла по всем комбинациям IP и порта следующим образом:
# use member-access enumeration to get ip and port arrays,
# and filter out $null or empty string values
$ips = $csv.IP | where-object { $_ }
$ports = $csv.Port | where-object { $_ }
foreach( $ip in $ips )
{
foreach( $port in $ports )
{
"{0} = {1}" -f $ip, $port
Test-NetConnection -ComputerName $ip -Port $port -InformationLevel Detailed
}
}
Если у вас есть 1 IP и 1 порт на строку CSV, можно упростить код, переименовав столбец IP
в ComputerName
:
Затем, поскольку оба параметра (-ComputerName
и -Port
) принимают входные данные конвейера по имени свойства, вы можете передать выходные данные из Import-Csv
непосредственно в Test-NetConnection
:
$csv_path = Read-Host -Prompt "Enter file path"
Import-Csv -Path $csv_path | Test-NetConnection -InformationLevel Detailed
Другой вариант, если вы хотите иметь несколько портов в строке с разделителем, например точкой с запятой:
Вы можете разделить точку с запятой на свойстве .Port
и использовать ту же логику, что и выше, создать по одному объекту для каждого порта со свойствами, которые можно привязать из конвейера:
Import-Csv -Path $csv_path | ForEach-Object {
foreach ($port in $_.Port -split '\s*;\s*') {
[pscustomobject]@{
ComputerName = $_.IP
Port = $port
}
}
} | Test-NetConnection -InformationLevel Detailed
Используя этот (многофункциональный) JoinModule (см. также: https://github.com/iRon7/Join-Object):
# "Import-Csv -Path $csv_path"
# Using your question data for a full Minimal, Reproducible Example:
Install-Script -Name Read-HtmlTable
$Data = Read-HtmlTable https://stackoverflow.com/q/78822669/1701026 -Table 0
Install-Module -Name JoinModule
$Data.Ip | CrossJoin $Data.Port | ForEach-Object { "{0} = {1}" -f @($_) }
1.1.1.1 = 22
1.1.1.1 = 25
1.1.1.1 = 80
1.1.1.1 =
1.1.1.2 = 22
1.1.1.2 = 25
1.1.1.2 = 80
1.1.1.2 =
1.1.1.3 = 22
1.1.1.3 = 25
1.1.1.3 = 80
1.1.1.3 =
1.1.1.4 = 22
1.1.1.4 = 25
1.1.1.4 = 80
1.1.1.4 =
Если вы хотите пропустить пустой Port
:
$Ports = $Data.Port | Where-Object { $_ }
$Data.Ip | CrossJoin $Ports | ForEach-Object { "{0} = {1}" -f @($_) }
1.1.1.1 = 22
1.1.1.1 = 25
1.1.1.1 = 80
1.1.1.2 = 22
1.1.1.2 = 25
1.1.1.2 = 80
1.1.1.3 = 22
1.1.1.3 = 25
1.1.1.3 = 80
1.1.1.4 = 22
1.1.1.4 = 25
1.1.1.4 = 80