使用foreach循环执行Powershell脚本后,结果太多

时间:2019-09-27 23:48:02

标签: powershell loops

我刚刚开始使用Powershell,并且正在做一些基本的脚本编写工作,从foreach和if,elseif构造开始。

我遇到了foreach循环的问题。

我试图用用户给定的参数编写一个简单的代码。我有一个包含2列的CSV文件:Zenskie(女)和Meskie(男)充满了姓名。我的代码是在CSV中查找用户提供的名称,并在输出中提供有关性别的信息。

CSV文件的一部分:

Zenskie;Meskie
Ada;Aaron
Adamina;Abdon
Adela;Abel
Adelajda;Abelard
Adriana;Abraham
Adrianna;Achilles
Agata;Adam
Agnieszka;Adelard
Aida;Adnan
Bogna;Dawid

我也为我的妻子添加了一些扭曲之处-应该只针对她的名字进行特别评论,在这里我遇到了问题。结果是应该的,但是显示了多次(我猜想是CSV中的行)。

如果列表中没有用户提供的输入,我也尝试在末尾添加一个“ else”部分。但是,当我这样做时,它给出了先前“ elseif”的结果。

我试图将另一个elseif与“ elseif($ UserName -ne $ Man)一起使用,但它也给了我错误的答案。

我敢打赌,我在这里错过了一些简单的事情...


Param (
  [string]$UserName = (Read-Host " Tell me your name ")
)

$Names = Import-Csv -Path C:\Powershell\Moje_nowe\Lista_imion3.csv -Delimiter ";"

ForEach ($item in $Names) {
  $Women = $item.("Zenskie")
  $Man = $item.("Meskie")
  if ($UserName -eq $Women) {
    Write-Output "$UserName you are women!"
  }
  elseif ($UserName -eq $Man) {
    Write-Output "$UserName you are man!"
  }
  elseif ($UserName -eq "Bogna") {
    Write-Output "Kiss me!! :)"
  }
  else {
    Write-Output "$UserName you have an odd name"
  }
}

预期结果:

输入Bogna:

Tell me your name: bogna

Kiss me!! :)

实际结果:

Kiss me!! :)

Kiss me!! :)

Kiss me!! :)

以此类推

当输入不在列表中时添加零件时:

预期:

Tell me your name: bdsdsd


bdsdsd you have an odd name

实际:

无论我输入什么

bdsdsd you have an odd name

bdsdsd you have an odd name

bdsdsd you have an odd name

以此类推

3 个答案:

答案 0 :(得分:1)

您可以使用“执行...直到”循环来保持游戏的运行...;-)

$CSV = @'
Zenskie;Meskie
Ada;Aaron
Adamina;Abdon
Adela;Abel
Adelajda;Abelard
Adriana;Abraham
Adrianna;Achilles
Agata;Adam
Agnieszka;Adelard
Aida;Adnan
Bogna;Dawid
'@ | ConvertFrom-Csv -Delimiter ';'

do {
    $UserName = Read-Host " Tell me your name (End with 'quit')" 
    if ($UserName -eq 'Bogna') { "Kiss me!! :)" }
    elseif ($UserName -in $CSV.Zenskie) { "$UserName you are woman!" }
    elseif ($UserName -in $CSV.Meskie) { "$UserName you are man!" }
    else  { "$UserName you have an odd name" }
} until ($Username -eq 'quit')

答案 1 :(得分:1)

  

结果是应该的,但是显示了多次(我猜想是CSV中的行数)。

实际上:假设您逐个循环从CSV行导入的对象,则if语句对每个 进行评估。

breakif分支中找到匹配项后,使用elseif退出循环(但不能在{ {1}}分支,因为它可能必须等待所有 all 对象被检查,以推断未找到匹配项。

注意事项仅在else 循环(声明)(如您的问题)中使用break,而不是在带有foreach cmdlet 管道(与accepted answer一样)。在后一种情况下,ForEach-Object在调用堆栈中查找封闭循环,如果找不到,则将整个脚本退出
简而言之:仅在循环breakbreak,...)或{{1中使用continueforeach }}声明whileswitch与管道完全无关(但是您可以在break脚本块中使用continue跳到 next 管道输入对象)。

从PowerShell v7开始,不直接支持按需中断(退出)管道this GitHub issue中要求添加此类支持。

但是,利用-in 的优势更简单,更高效。 PowerShell的数组成员资格测试(包含)运算符(PSv3 +;在PSv2中,或者使用{ {1}}(操作数顺序相反),它允许您对所有CSV行执行单个测试(每个比较值),如{{ 3}}。

一个简化的示例:

注意:下面的代码首先将所有CSV数据读取到内存中,然后为两列中的值从中创建两个数组。对于具有名字列表的文件,这不应该是内存问题。但是,在处理大型输入数据集时,您可能需要一个解决方案来在管道中逐行处理输入CSV文件。

return

以上结果:

ForEach-Object

答案 2 :(得分:-1)

尝试:

Param ([string]$UserName = (Read-Host " Tell me your name " ))

#if Bogna, not necessary to loop, print and out
if ($UserName -eq "Bogna")
{
   "Kiss me!! :)  (nice declaration)"
   return
}

#loop on all elements and if you found as you want, break for not continue ==> attention break leave the programm in pipe foreach
$FirstElement=Import-csv -Path "C:\Powershell\Moje_nowe\Lista_imion3.csv" -Delimiter ";" | %{

    if ($_.Zenskie -eq $UserName)
    {
        "$UserName you are women!"

        break
    }
    elseif ($_.Meskie -eq $UserName)
    {
        "$UserName you are man!"

        break
    }

}

# BE CAREFULL IF BREAK IS RAISED THE SCRIPT IS ENDED AND THIS CODE DOESNT EXECUTED
if (! $FirstElement)
{
"$UserName you have an odd name, Brrrrr !"
}

如果您的脚本在csv循环后继续执行,请不要使脚本处于中断状态,您可以这样做:

Param ([string]$UserName = (Read-Host " Tell me your name " ))

#if Bogna, not necessary to loop, print and out
if ($UserName -eq "Bogna")
{
   "Kiss me!! :)  (nice declaration)"
   return
}

#loop on all elements and if you found as you want, break for not continue
$FirstElement=$null

$allElement=Import-csv -Path "C:\Powershell\Moje_nowe\Lista_imion3.csv" -Delimiter ";"

foreach ($item in $allElement)
{
     if ($item.Zenskie -eq $UserName)
    {
        "$UserName you are women!"
        $FirstElement=$item
        break
    }
    elseif ($item.Meskie -eq $UserName)
    {
        "$UserName you are man!"
        $FirstElement=$item
        break
    }
}

#if not element founded
if (! $FirstElement)
{
    "$UserName you have an odd name, Brrrrr !"
}