【问题标题】:How to handle foreach loop Powershell two times?如何处理foreach循环Powershell两次?
【发布时间】:2020-11-09 06:37:25
【问题描述】:

我在 foreach 循环中有 foreach 循环。我做了一些字符串处理并用特定的字符串映射一个文件。 我使用消息框让用户知道哪个文件匹配或不匹配。我试过这个,它有效,但消息框显示 6 次,但它应该是 3 次。任何人都可以帮助我。谢谢。

Add-Type -AssemblyName PresentationFramework
Add-Type -AssemblyName System.Windows.Forms
[System.Windows.Forms.Application]::EnableVisualStyles()

$Process = "D:\Pro"
$AllFiles = Get-ChildItem -Path $Process\*.pro -File | ForEach-Object {$_.BaseName.Substring(45)}
$Selected = @("XY11WWOLAT601A1ABA", "XY11WWOLAT601APABA", "XY11WWOLAT601ZHABA") | ForEach-Object {$_.Substring(2,13)}

foreach ($job in $AllFiles)
{
    
     $JobSplit = $job -split "_"
     $Name =  [string]::Concat($JobSplit)

     foreach ($SW in $Selected)
     {
          if ($SW -like "*$Name")
          {
               [System.Windows.Forms.MessageBox]::Show("This SW: $SW`nNOT available.","[Error]" , "OK", "Error")
          
          }
          else {

               [System.Windows.Forms.MessageBox]::Show("This SW: $SW`nAvailable.","[Info]" , "OK", "Info")     
          }
     }         
}

这是AllFiles 示例: 123456789A_A2E9D28DA533_20200702045123_XX_ABC11WWOLAT601_A1.pro 123456789A_A2E9D28DA533_20200702011155_XX_ABC11WWOLAT601_ZH.pro

【问题讨论】:

  • 抱歉,meeage 框只显示了 3 次。你确定你在 d:\pro 中只有一个文件吗?重新加载你的 PowerShell。
  • 不,我在d:\pro@JPBlanc 中有多个文件
  • 因此,对于每个文件,消息出现 3 次。
  • 当我用一个文件运行它时,这不是 cas。
  • @SBR 这样的讨论是没有用的。通过一个最小的例子告诉我们如何准确地重现您的问题。然后我们可以看看这个确切的问题。因此,当您只为我们提供一个文件名(这很好并且希望足够)时,然后描述/讨论由这个文件名引起的问题。长话短说:如果D:\pro 中只有一个文件,您会收到哪些消息/错误?

标签: powershell loops foreach


【解决方案1】:

您误解了嵌套循环的工作原理。 对于外循环中的每个数据对象,在内循环中处理数据对象。

例子:

1..3 | 
ForEach {
"`n *** Processing outloop $PSItem *** `n"
    'a','b','c' | 
    ForEach {
        "Processing innerloop $PSItem"
    }
}
# Results
<#
*** Processing outloop 1 *** 

Processing innerloop a
Processing innerloop b
Processing innerloop c

*** Processing outloop 2 *** 

Processing innerloop a
Processing innerloop b
Processing innerloop c

*** Processing outloop 3 *** 

Processing innerloop a
Processing innerloop b
Processing innerloop c
#>

所以...至于您的代码...

Add-Type -AssemblyName PresentationFramework
Add-Type -AssemblyName System.Windows.Forms
[System.Windows.Forms.Application]::EnableVisualStyles()

$Process  = "D:\Pro"

# ForEach #1
$AllFiles = Get-ChildItem -Path $Process\*.pro -File | 
ForEach-Object {$_.BaseName.Substring(45)}

# ForEach #2
$Selected = @("XY11WWOLAT601A1ABA", "XY11WWOLAT601APABA", "XY11WWOLAT601ZHABA") | 
ForEach-Object {$_.Substring(2,13)}


<#
ForEach #3 that use the results of ForEach #1
This is the outer ForLoop
This will process for each data object
So, whatever the count of $Allfiles is each must be process X times
#>
foreach ($job in $AllFiles)
{
     "Processing job $job in the outer loop"
     $JobSplit = $job -split "_"
     $Name =  [string]::Concat($JobSplit)

    <#
    ForEach #4 that use the results of ForEach #2
    This is the inner ForLoop
    This will process 3 times for each data object in the outerloop
    Each much be processed for each data object in $AllFiles.
    #>
     foreach ($SW in $Selected)
     {
        "Processing SW $SW in the inner loop"
          if ($SW -like "*$Name")
          {
               [System.Windows.Forms.MessageBox]::Show("This SW: $SW`nNOT available.","[Error]" , "OK", "Error")
          
          }
          else {

               [System.Windows.Forms.MessageBox]::Show("This SW: $SW`nAvailable.","[Info]" , "OK", "Info")     
          }
     }         
}

【讨论】:

  • @posanote 谢谢你的建议。但它仍然出现了 6 次。在命令中它显示了这个OK OK OK OK OK OK
  • 我期望它只出现 3 次,因为我只有 3 个 $Selected 数组。
  • 不用担心。如果您只有 1 个来自 $AllFiles 的数据对象,您只会得到 3 个。所以,如果你只有 3 个响应,你就不想使用嵌套循环。
【解决方案2】:

这里不需要第二个循环。

不过,您的问题有一些不一致之处。

你说:

我使用消息框让用户知道哪个文件匹配或不匹配

然后

它有效,但消息框显示 6 次,但它应该是 3 次

并提供 2 个文件名示例作为参考

123456789A_A2E9D28DA533_20200702045123_XX_ABC11WWOLAT601_A1.pro 123456789A_A2E9D28DA533_20200702011155_XX_ABC11WWOLAT601_ZH.pro

如果您希望每个文件有 1 个消息框来说明它是否与字符串匹配,那么您最终会得到 2 消息框。不是 3,不是 6。

现在,你的实际问题。 您只需要一个一个地遍历所有文件并验证它们是否是$Selected 的一部分。第二部分不需要第二个循环。相反,我们将使用.where 方法确定文件名是否匹配。

foreach ($Job in $AllFiles) {
    $Selection = $Selected.Where( { $_ -like "*$Job" },'first')
    
    if ($Selection.count -gt 0) {
        [void][System.Windows.Forms.MessageBox]::Show("This SW: $($Selection[0])`nNOT available.", "[Error]" , "OK", "Error")
    }
    else {
        [void][System.Windows.Forms.MessageBox]::Show("This SW: $Job`nAvailable.", "[Info]" , "OK", "Info")     
    }
}

如果我弄错了,而您真的想要 3 个消息框,因此 $Selected 中的每个项目 1 个消息框而不是每个文件 1 个消息框,那么您只需为此更改 foreach 循环一:


foreach ($SW in $Selected) {
    $Selection = $AllFiles.Where( { $SW -like "*$_" }, 'first')

    if ($Selection.Count -eq 1) {
        [void][System.Windows.Forms.MessageBox]::Show("This SW: $SW`nNOT available.", "[Error]" , "OK", "Error")
    }
    else {
        [void][System.Windows.Forms.MessageBox]::Show("This SW: $SW`nAvailable.", "[Info]" , "OK", "Info")     
    }
}

【讨论】:

  • 谢谢@Sage Pourpre 赞赏!但是它只在选择匹配时显示消息框,一旦选择不匹配它就不会显示消息框。我希望消息框可以显示两种情况
  • 谢谢@Sage。我对您的回答做了一些修改,然后它按我的预期工作。太感谢了。非常感谢! ` foreach ($sel in $Selection) { $Files = $AllFiles.Where( { $_ -like "*$sel*" }) if ($Files.count -gt 0) { [void][System.Windows.Forms.MessageBox]::Show("This SW: $($Files[0])nNOT available.", "[Error]" , "OK", "Error") } else { [void][System.Windows.Forms.MessageBox]::Show("This SW: $sel Available. ", "[信息]" , "OK", "信息") } }`
猜你喜欢
  • 1970-01-01
  • 2011-06-01
  • 2021-10-25
  • 1970-01-01
  • 2020-08-26
  • 1970-01-01
  • 1970-01-01
  • 2019-09-19
  • 1970-01-01
相关资源
最近更新 更多