使用foreach循环执行powershell脚本后的结果过多

使用foreach循环执行powershell脚本后的结果过多,powershell,loops,Powershell,Loops,我刚刚开始我的Powershell之旅,我正在做一些基本的脚本编写,从foreach和if,elseif结构开始 我对foreach循环有问题 我试图用用户给定的参数编写一个简单的代码。我有一个CSV文件,有两列:Zenskie(女性)和Meskie(男性)填写了姓名。我的代码是在CSV中查找用户提供的姓名,并作为输出提供有关性别的信息 CSV文件的一部分: Zenskie;Meskie Ada;Aaron Adamina;Abdon Adela;Abel Adelajda;Abelard Ad

我刚刚开始我的Powershell之旅,我正在做一些基本的脚本编写,从foreach和if,elseif结构开始

我对foreach循环有问题

我试图用用户给定的参数编写一个简单的代码。我有一个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=(读主机“告诉我你的名字”)
)
$Names=导入Csv-路径C:\Powershell\Moje\u nowe\Lista\u imion3.Csv-分隔符”;"
ForEach($名称中的项目){
$Women=$item.(“Zenskie”)
$Man=$item.(“梅斯基”)
如果($UserName-eq$Women){
写入输出“$UserName您是女性!”
}
elseif($UserName-eq$Man){
写入输出“$UserName您就是男人!”
}
elseif($UserName-eq“Bogna”){
编写输出“吻我!!:)”
}
否则{
写入输出“$UserName您有一个奇数名称”
}
}

预期结果:

对于输入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
依此类推,你可以用“do…”。。。直到“循环以保持游戏运行…;-)

试试这个:

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循环后继续,请不要将脚本保留为break,您可以执行以下操作:

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 !"
}
结果是应该的,但它显示了多次(我猜是CSV中的行数)

事实上:假设您分别循环从CSV行导入的对象,则会对每个行计算
if
语句

if
elseif
分支中找到匹配项后,使用
break
退出循环,以修复该问题(但不能在
else
分支中,因为它必须等待检查所有对象,以推断未找到匹配项)

注意事项仅在
foreach
循环(语句)(如您的问题所示)中使用
break
,而不是在管道中使用
foreach对象
cmdlet
(如中)。在后一种情况下,
break
在调用堆栈上查找封闭循环,如果没有找到,则作为一个整体退出脚本。
简而言之:只在循环(
foreach
while
,…)或
switch
语句中使用
break
continue
与管道完全无关(但您可以在
ForEach对象
脚本块中使用
return
,跳到下一个管道输入对象)

从PowerShell v7开始,对于按需中断(退出)管道没有直接支持;中正在请求添加此类支持

但是,利用
PowerShell的数组成员资格测试(包含)操作符(PSv3+;在PSv2中,或者在操作数顺序相反的情况下使用
-contains
)更简单、更有效,它允许您执行单个测试(每个比较值)跨所有CSV行
,如中所示

一个简化的例子:

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

上述收益率:

Abdon,你是个男人。 Pocałuj mnie!!:) 阿德拉,你是个女人。 比尔,你的名字很奇怪。
break
是一个错误的命令,因为在没有封闭循环的情况下,它作为一个整体退出脚本;
break
不能用于退出管道-除非在管道周围使用
break
虚拟循环,否则目前无法提前退出管道-请参阅。简而言之:您的代码碰巧是可行的,但这只是因为在这种情况下循环后不需要运行代码;如果有其他代码要运行,它就不会运行。我仍然+1您的建议,即使它在大文件上会产生反作用。您遍历所有行2次,并将所有内容存储在内存中,对于要测试的每个名称,您可能会测试所有人和潜力所有女性都可以找到你的解决方案,而不是浏览一次csv列表并测试每行的所有姓名(一般来说,你正在寻找的内容数量远低于你在计算机科学中搜索的内容,尤其是csv)@esperento 57:感谢您更新您的答案;重新设计决策:我同意这是不幸的,但问题是现在更改行为可能会破坏现有代码。re大文件:是的,但我们正在处理一个名字列表,它不太可能太大而无法放入内存或需要很长时间才能加载;不过,我添加了一个注释答案是肯定的。
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 !"
}
# Parse sample CSV input into objects with .Zenskie and .Meskie properties.
$names = @'
Zenskie;Meskie
Ada;Aaron
Adamina;Abdon
Adela;Abel
'@ | ConvertFrom-Csv -Delimiter ';'

# Extract the male and female names into individual arrays.
# Note how no quoting is needed to acces the properties (columns) by names
# and how accessing a property on the input array ($names) automatically
# returns the property values *from all array elements*, a feature known
# as member enumeration.
$maleNames = $names.Meskie
$femaleNames = $names.Zenskie

# Test a few sample names.
'Abdon', 'Bogna', 'Adela', 'Bill' | ForEach-Object {

  if ($_ -eq 'Bogna') { # exception
    "Pocałuj mnie!! :)"
  }
  elseif ($_ -in $maleNames) { # -in tests presence in the array, case-insensitively
    "$_, you are a man."
  }
  elseif ($_ -in $femaleNames) {    
    "$_, you are a woman."
  }
  else {
    "$_, you have an odd name."
  }

}