我刚刚开始使用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
以此类推
答案 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
语句对每个 进行评估。
在break
和if
分支中找到匹配项后,使用elseif
退出循环(但不能在{ {1}}分支,因为它可能必须等待所有 all 对象被检查,以推断未找到匹配项。
注意事项:仅在else
循环(声明)(如您的问题)中使用break
,而不是在带有foreach
cmdlet 的管道(与accepted answer一样)。在后一种情况下,ForEach-Object
在调用堆栈中查找封闭循环,如果找不到,则将整个脚本退出。
简而言之:仅在循环(break
,break
,...)或{{1中使用continue
和foreach
}}声明; while
和switch
与管道完全无关(但是您可以在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 !"
}