powershell 如何检查数组中的一行是否包含另一个数组中的内容

hivapdat  于 2023-06-29  发布在  Shell
关注(0)|答案(3)|浏览(199)

最终,我试图3阵列一样的项目,并把这些一样的项目在一起,他们的颜色。但现在我只是想检查数组$line中的一行是否与另一个数组$colors中的任何内容都不匹配,

$itemsofCars =@()
$cars = @()
$colors =  Get-Content "C:\Newfolder\colors.txt"
$typefile = Get-Content "C:\Newfolder\cars_not_formatted.txt"
$carBlock = @("1")
foreach ($line in $typefile)

        {
            if($line.Contains("_Wheel") -or
               $line.Contains("Doors") -or
               $line.Contains("trunk") -or
               $line.Contains("hood") -or
               $line.Contains("coDriver") -or
               $line.Contains("_driver")
               ) 
            { 
                   $itemsofCars += $line
             }
          else
          {
             $cars += $line
          }               
        }
#$itemsofCars
#$cars
#foreach ($car in $cars)
#  {
#    Add-Content 'C:\Newfolder\test.txt'  $itemsofCars 
# }

 foreach ($line in $cars)

        {
            #trying to check if the line in car contains a color, if not then add to carBlock
            if($line.ToUpper() -notcontains $colors.ToUpper())
            {
                #making sure there isn't duplicates
                if($carBlock.ToUpper() -notcontains $car.ToUpper())
                {
                    $carBlock = $line 
                    $carBlock
                }
            }
            else
            {
                
            }
        }

这是一部分汽车文件

BRDM
BRDM_Wheel
BRDM_Doors_Driver
BRDM_Doors_coDriver
BRDM_Doors_hood
BRDM_Doors_trunk
BRDM_Doors_Driver_Woodland
BRDM_Doors_coDriver_Woodland
BRDM_Doors_hood_Woodland
BRDM_Doors_trunk_Woodland
BRDM_Doors_Driver_black
BRDM_Doors_coDriver_black
BRDM_Doors_hood_black
BRDM_Doors_trunk_black
BRDM_Doors_Driver_Pixel
BRDM_Doors_coDriver_Pixel
BRDM_Doors_hood_Pixel
BRDM_Doors_trunk_Pixel
BRDM_Doors_Driver_Camouflage
BRDM_Doors_coDriver_Camouflage
BRDM_Doors_hood_Camouflage
BRDM_Doors_trunk_Camouflage
BRDM_Doors_Driver_Flecktarn
BRDM_Doors_coDriver_Flecktarn
BRDM_Doors_hood_Flecktarn
BRDM_Doors_trunk_Flecktarn
BRDM_Woodland
BRDM_black
BRDM_Pixel
BRDM_Camouflage
BRDM_Flecktarn

这是颜色文件

Woodland
Black
Pixel
Camouflage
Flecktarn
ZSU
Grey
Desert
Chrome
Winter
Scull
Blue
Orange
Red
Green
lightgreen
kamo
union
white
Gold
Samurai
grey
blue
kamo2
BIOHAZARD
CAMOgreen
carbon
Flora
GVILORD
skul
beige
chaki2
MCHS
les
umbr

我已经重新安排了无数次代码,但还是不能让它工作。我能做些什么来实现它?

fslejnso

fslejnso1#

你的代码对于你想要实现的目标来说似乎过于复杂,你可以从你的colors.txt文件和if条件中的所有部分创建正则表达式模式,然后你可以使用带有-Regex-File标志的switch来逐行读取和匹配这些模式,然后将它们存储在自己的集合中。
最后,枚举每个集合并输出到文件。

$parts = ('_Wheel', 'Doors', 'trunk', 'hood', 'coDriver', '_driver' | ForEach-Object { [regex]::Escape($_) }) -join '|'
$colors = (Get-Content .\colors.txt | ForEach-Object { [regex]::Escape($_) }) -join '|'

$result = @{
    itemsofCars = [System.Collections.Generic.List[string]]::new()
    cars        = [System.Collections.Generic.List[string]]::new()
    colorsofCar = [System.Collections.Generic.List[string]]::new()
}

switch -Regex -File .\cars_not_formatted.txt {
    $parts { $result['itemsofCars'].Add($_); continue }
    $colors { $result['colorsofCar'].Add($_); continue }
    default { $result['cars'].Add($_) }
}

$result.GetEnumerator() | ForEach-Object { $_.Value | Set-Content ($_.Key + '.txt') }

如果你需要保留内存,你也可以使用3个可步进的管道而不是3个列表:

# `$parts` and `$colors` are defined here the same way

$result = @{
    itemsofCars = { Set-Content .\itemsofCars.txt }.GetSteppablePipeline()
    cars        = { Set-Content .\cars.txt }.GetSteppablePipeline()
    colorsofCar = { Set-Content .\colorsofCars.txt }.GetSteppablePipeline()
}

$result.GetEnumerator() | ForEach-Object { $_.Value.Begin($true) }

switch -Regex -File .\cars_not_formatted.txt {
    $parts { $result['itemsofCars'].Process($_); continue }
    $colors { $result['colorsofCar'].Process($_); continue }
    default { $result['cars'].Process($_) }
}

$result.GetEnumerator() | ForEach-Object { $_.Value.End() }
gfttwv5a

gfttwv5a2#

两个数组的输出;颜色和部件-匹配行和不匹配行。
使用foreach嵌套循环来控制并使用-match比较运算符列出每个数组中的匹配行。
另外还有两个Compare-Object命令,用于列出每个数组中与另一个数组中的任何行都不匹配的值(即不匹配项)。

PowerShell(匹配)

$Parts = Get-Content "E:\Parts.txt";
$Colors = Get-Content "E:\Colors.txt";

## -- Show matching part to matching color
foreach ($part In $Parts) {
    foreach ($color In $Colors) {
        if ($part -match $color) {
            "Part: $($part.ToUpper()), Color: $($color.ToUpper())"
        }
    }
};

输出

Part: BRDM_DOORS_DRIVER_WOODLAND, Color: WOODLAND
Part: BRDM_DOORS_CODRIVER_WOODLAND, Color: WOODLAND
Part: BRDM_DOORS_HOOD_WOODLAND, Color: WOODLAND
Part: BRDM_DOORS_TRUNK_WOODLAND, Color: WOODLAND
Part: BRDM_DOORS_DRIVER_BLACK, Color: BLACK
Part: BRDM_DOORS_CODRIVER_BLACK, Color: BLACK
Part: BRDM_DOORS_HOOD_BLACK, Color: BLACK
Part: BRDM_DOORS_TRUNK_BLACK, Color: BLACK
Part: BRDM_DOORS_DRIVER_PIXEL, Color: PIXEL
Part: BRDM_DOORS_CODRIVER_PIXEL, Color: PIXEL
Part: BRDM_DOORS_HOOD_PIXEL, Color: PIXEL
Part: BRDM_DOORS_TRUNK_PIXEL, Color: PIXEL
Part: BRDM_DOORS_DRIVER_CAMOUFLAGE, Color: CAMOUFLAGE
Part: BRDM_DOORS_CODRIVER_CAMOUFLAGE, Color: CAMOUFLAGE
Part: BRDM_DOORS_HOOD_CAMOUFLAGE, Color: CAMOUFLAGE
Part: BRDM_DOORS_TRUNK_CAMOUFLAGE, Color: CAMOUFLAGE
Part: BRDM_DOORS_DRIVER_FLECKTARN, Color: FLECKTARN
Part: BRDM_DOORS_CODRIVER_FLECKTARN, Color: FLECKTARN
Part: BRDM_DOORS_HOOD_FLECKTARN, Color: FLECKTARN
Part: BRDM_DOORS_TRUNK_FLECKTARN, Color: FLECKTARN
Part: BRDM_WOODLAND, Color: WOODLAND
Part: BRDM_BLACK, Color: BLACK
Part: BRDM_PIXEL, Color: PIXEL
Part: BRDM_CAMOUFLAGE, Color: CAMOUFLAGE
Part: BRDM_FLECKTARN, Color: FLECKTARN

PowerShell(无匹配项)

$Parts = Get-Content "E:\Parts.txt";
$Colors = Get-Content "E:\Colors.txt";

$Matches = foreach ($part In $Parts) {
    foreach ($color In $Colors) {
        if ($part -match $color) {
            "$($part.ToUpper()), $($color.ToUpper())"
        }
    }
};

## Show non-matching parts
(Compare-Object $matches.ForEach({$_.split(",")[0]}) $Parts).InputObject | Select-Object @{N="Mismatch part";E={$_.ToUpper()}};

## Show non-matching colors
(Compare-Object $matches.ForEach({$_.split(",")[1]}).Trim() $Colors | 
    Where-Object {$_.SideIndicator -eq "=>"}).InputObject | 
        Select-Object @{N="Mismatch color";E={$_.ToUpper()}};

输出

Mismatch part      
-------------      
BRDM               
BRDM_Wheel         
BRDM_Doors_Driver  
BRDM_Doors_coDriver
BRDM_Doors_hood    
BRDM_Doors_trunk   

Mismatch color
--------------
ZSU           
Grey          
Desert        
Chrome        
Winter        
Scull         
Blue          
Orange        
Red           
Green         
lightgreen    
kamo          
union         
white         
Gold          
Samurai       
grey          
blue          
kamo2         
BIOHAZARD     
CAMOgreen     
carbon        
Flora         
GVILORD       
skul          
beige         
chaki2        
MCHS          
les           
umbr

支持资源

gwbalxhn

gwbalxhn3#

对于此问题,您可以考虑使用ScriptProperty成员,这些成员会在后期将属性值绑定到对象,这意味着您可以在创建$Cars列表之后向$Colors$Parts列表添加项

$Names  = 'BRDM', 'BRDM_Wheel', 'BRDM_Doors_Driver', 'BRDM_Doors_coDriver', 'BRDM_Doors_hood', 'BRDM_Doors_trunk', 'BRDM_Doors_Driver_Woodland', 'BRDM_Doors_coDriver_Woodland', 'BRDM_Doors_hood_Woodland', 'BRDM_Doors_trunk_Woodland', 'BRDM_Doors_Driver_black', 'BRDM_Doors_coDriver_black', 'BRDM_Doors_hood_black', 'BRDM_Doors_trunk_black', 'BRDM_Doors_Driver_Pixel', 'BRDM_Doors_coDriver_Pixel', 'BRDM_Doors_hood_Pixel', 'BRDM_Doors_trunk_Pixel', 'BRDM_Doors_Driver_Camouflage', 'BRDM_Doors_coDriver_Camouflage', 'BRDM_Doors_hood_Camouflage', 'BRDM_Doors_trunk_Camouflage', 'BRDM_Doors_Driver_Flecktarn', 'BRDM_Doors_coDriver_Flecktarn', 'BRDM_Doors_hood_Flecktarn', 'BRDM_Doors_trunk_Flecktarn', 'BRDM_Woodland', 'BRDM_black', 'BRDM_Pixel', 'BRDM_Camouflage', 'BRDM_Flecktarn'
$Colors = 'Woodland', 'Black', 'Pixel', 'Camouflage', 'Flecktarn', 'ZSU', 'Grey', 'Desert', 'Chrome', 'Winter', 'Scull', 'Blue', 'Orange', 'Red', 'Green', 'lightgreen', 'kamo', 'union', 'white', 'Gold', 'Samurai', 'grey', 'blue', 'kamo2', 'BIOHAZARD', 'CAMOgreen', 'carbon', 'Flora', 'GVILORD', 'skul', 'beige', 'chaki2', 'MCHS', 'les', 'umbr'
$Parts  = 'Wheel', 'Doors', 'trunk', 'hood', 'coDriver', 'driver'
$ColorScript = { $Colors.Where{ $This.Name.Split('_') -Contains $_ } }
$PartsScript = {  $Parts.Where{ $This.Name.Split('_') -Contains $_ } }
# $Cars = Get-Content .\cars_not_formatted.txt |Foreach-Object { ...
$Cars = $Names |Foreach-Object { [PSCustomObject]@{ Name = $_ } } |
 Add-Member -MemberType ScriptProperty -Name Color -Value $ColorScript -PassThru |
 Add-Member -MemberType ScriptProperty -Name Parts -Value $PartsScript -PassThru
$Cars |Where-Object Parts -Contains hood

Name                       Color      Parts
----                       -----      -----
BRDM_Doors_hood                       {Doors, hood}
BRDM_Doors_hood_Woodland   Woodland   {Doors, hood}
BRDM_Doors_hood_black      Black      {Doors, hood}
BRDM_Doors_hood_Pixel      Pixel      {Doors, hood}
BRDM_Doors_hood_Camouflage Camouflage {Doors, hood}
BRDM_Doors_hood_Flecktarn  Flecktarn  {Doors, hood}
$Cars |Where-Object Color -eq Woodland |Select-Object -Expand Name

BRDM_Doors_Driver_Woodland
BRDM_Doors_coDriver_Woodland
BRDM_Doors_hood_Woodland
BRDM_Doors_trunk_Woodland
BRDM_Woodland

如果您不想执行“(PSCustom)Object Oriented Programming",您甚至可以考虑将ScriptProperty成员直接添加到字符串中,这些字符串本身实际上是(PowerShell)对象。例如,参见$Cars[0].PSTypeNames
添加的(string)成员将不会显示在字符串输出中,并且在处理时很容易消失:

$ColorScript = { $Colors.Where{ $This.Split('_') -Contains $_ } }
$PartsScript = {  $Parts.Where{ $This.Split('_') -Contains $_ } }
# $Cars = Get-Content .\cars_not_formatted.txt | ...
$Cars = $Names |
 Add-Member -MemberType ScriptProperty -Name Color -Value $ColorScript -PassThru |
 Add-Member -MemberType ScriptProperty -Name Parts -Value $PartsScript -PassThru
$Cars |Where-Object Color -eq Black
BRDM_Doors_Driver_black
BRDM_Doors_coDriver_black
BRDM_Doors_hood_black
BRDM_Doors_trunk_black
BRDM_black

由于两个ScriptProperty成员实际上是相同的,并且直接(不带参数)从父作用域中提取$Color$Parts列表是一种不好的做法,因此您也可以考虑使用ScriptMethod并传递相关的项列表。

$Cars = $Names |Add-Member -MemberType ScriptMethod -Name ListItem -Value {
    $Args |Foreach-Object { $_.Where{ $This.Split('_') -Contains $_ } }
}  -PassThru

$Cars |Where-Object { $_.ListItem($Colors) -eq 'Pixel' }
BRDM_Doors_Driver_Pixel
BRDM_Doors_coDriver_Pixel
BRDM_Doors_hood_Pixel
BRDM_Doors_trunk_Pixel
BRDM_Pixel

请注意,不幸的是,这个$Cars |Where-Object ContainsItem($Colors) -eq 'Pixel'不能按预期工作,请参阅:#8224 "Where-Object -Property ..." should not accept method names because they're not properties

相关问题