代码之家  ›  专栏  ›  技术社区  ›  S K

需要在Powershell中使用2个变量为CSV文件创建foreach循环

  •  0
  • S K  · 技术社区  · 11 月前

    我是编程新手,我的大部分经验都是Python。 我正在编写一个简单的powershell脚本,该脚本在CSV文件中的IP地址和端口上运行Test NetConnection。

    IP 港口
    1.1.1.1 22
    1.1.1.2 25
    1.1.1.3 80
    1.1.1.4

    每个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
    }
    
    3 回复  |  直到 11 月前
        1
  •  1
  •   mclayton    11 月前

    PowerShell有一个方便的功能,名为 Member-Access Enumeration 你可以在这里使用。

    简而言之,如果您访问数组对象上的属性或方法(例如 $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
    
        }
    }
    
        2
  •  1
  •   Joel Coehoorn    11 月前

    每个IP都需要使用每个端口进行测试

    所以,您正在检查所有四个IP的端口22、25和80?根据样本数据,总共进行了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
        }
    }
    
        3
  •  1
  •   Santiago Squarzon    11 月前

    如果每个CSV行有1个IP和1个端口,简化代码的一种方法是重命名 IP 列到 ComputerName :

    计算机名称 港口
    1.1.1.1 22
    1.1.1.2 25
    1.1.1.3 80

    然后,因为这两个参数( -ComputerName -Port )采取 pipeline input by Property Name ,您可以通过管道传输输出 Import-Csv 直接到 Test-NetConnection :

    $csv_path = Read-Host -Prompt "Enter file path"
    Import-Csv -Path $csv_path | Test-NetConnection -InformationLevel Detailed
    

    另一种选择是,如果您希望每行有多个端口,并使用分隔符,例如:分号:

    IP 港口
    1.1.1.1 22; 80
    1.1.1.2 25; 444
    1.1.1.3 80

    你可以用分号切开 .Port 属性和使用与上述相同的逻辑,为每个端口创建一个对象,其属性可以从管道绑定:

    Import-Csv -Path $csv_path | ForEach-Object {
        foreach ($port in $_.Port -split '\s*;\s*') {
            [pscustomobject]@{
                ComputerName = $_.IP
                Port         = $port
            }
        }
    } | Test-NetConnection -InformationLevel Detailed