为什么我不能从我的数组中调用Contains方法?
Arrrg!我遇到了我在PowerShell中编写的一个简单脚本,这是一个愚蠢的问题。我正在调用一个正在调用存储过程的sql命令,并将结果放到一个数组中。结果是这个样子:为什么我不能从我的数组中调用Contains方法?
Status ProcessStartTime ProcessEndTime
------ ---------------- --------------
Expired May 22 2010 8:31PM May 22 2010 8:32PM
我想要做的是if($s.Contains("Expired"))
,报告没有。简单...? :(我遇到的问题是它看起来像Contains方法没有被加载,因为我得到这样的错误:
方法调用失败,因为[System.Object []]不包含名为'包含在行:1个字符:12个 + $ s.Contains < < < <( “过期”) + CategoryInfo:InvalidOperation:(包含:字符串)[],的RuntimeException + FullyQualifiedErrorId:MethodNotFound
那么,我可以做些什么来阻止powershell将其展开为字符串?下面的实际ps脚本 -
$s = @(Invoke-Sqlcmd -Query "USE DB
GO
exec Monitor_TEST_ps 'EXPORT_RUN',NULL,20" `
-ServerInstance testdb002\testdb_002
)
if ($s.Contains("Expired"))
{
Write-Host "Expired found, FAIL."
}
else
{
Write-Host "Not found, OK."
}
您看到该方法的原因是Get-Members是powershell试图有帮助并展开集合。如果您有一个包含多种类型项目的数组,它会向您显示每种类型的成员(例如,如果您使用'ls'(Get-ChildItem)并且您所在的目录中有FileInfos和DirectoryInfos,并且您管理ls | gm ,它会显示FileInfos您成员还另一组DirectoryInfos的成员):
(7) C:\ -» ls
Directory: C:\
Mode LastWriteTime Length Name
---- ------------- ------ ----
d---- 5/28/2010 8:19 AM .hg
d---- 5/13/2010 3:37 PM Build
…
-a--- 4/22/2010 11:21 AM 2603 TODO.org
(8) C:\ -» ls | gm
TypeName: System.IO.DirectoryInfo
Name MemberType Definition
---- ---------- ----------
Mode CodeProperty System.String Mode{get=Mode;}
Create Method System.Void Create(System.Security.AccessControl.Direct...
…
TypeName: System.IO.FileInfo
Name MemberType Definition
---- ---------- ----------
Mode CodeProperty System.String Mode{get=Mode;}
AppendText Method System.IO.StreamWriter AppendText()
…
我最常做的,以确保我不是在看展开的成员,是尝试“$ s.GetType() .Name“首先看看我在处理什么。在你的情况下,它是清晰的和数组,因为你初始化它像“$ s = @(Invo”(@ =它是一个数组)
要找出一个数组是否包含项目,可以使用 - 包括运营商:
(9) C:\ -» @(1,2,3) -contains 1
True
我想你已经有了一个字符串数组,所以你可以使用一个字符串,如:
(10) C:\ -» @("Stuff","you've","got","might have","Expired") -contains "Expired"
True
但是,如果过期不完全匹配(你正在寻找一个包含过期的元素,比如“Connection Expired 1/1/2010”),你需要找到匹配并检查第二个e计数,我认为:
(23) C:\ -» @("Stuff","you've","got","might have","Connection Expired 1/1/2010") -contains "Expired"
False
(24) C:\ -» @("Stuff","you've","got","might have","Connection Expired 1/1/2010") | ?{$_.Contains("Expired")}
Connection Expired 1/1/2010
(33) C:\ -» $xs = @("Stuff","you've","got","might have","Connection Expired 1/1/2010") | ?{$_.Contains("Expired")}
(34) C:\ -» $xs.GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True String System.Object
(35) C:\ -» $xs
Connection Expired 1/1/2010
在这种情况下,只有一个匹配,所以powershell展开到一个字符串。混蛋。但是,如果有超过1个匹配,则:
(36) C:\ -» $xs = @("Stuff","you've","got","might Expired have","Connection Expired 1/1/2010") | ?{$_.Contains("Expired")}
(37) C:\ -» $xs.GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Object[] System.Array
(38) C:\ -» $xs
might Expired have
Connection Expired 1/1/2010
现在是一个数组。
幸运的是,字符串和数组的长度属性:
(39) C:\ -» $xs.Length
2
(40) C:\ -» "Bob".Length
3
所以,你可以检查你的结果中包含“已过期”的长度,看看是否有任何过期的:
(41) C:\ -» $xs = @("Stuff","you've","got","might Expired have","Connection Expired 1/1/2010") | ?{$_.Contains("Expired")}
(42) C:\ -» if ($xs.Length -gt 0) { Write-Host "Whoas, stuff's expired, dog." }
Whoas, shit's expired, dog.
(也许有人有更好的方法来检查,如果一个集合包含一个项目,可以满足某些谓词(如LINQ的任何)?)
简单地说,$ s是一个.NET数组重新使用@()
确保),并且您试图调用此.NET类型中不存在的方法(Contains)。
解决您的问题,最简单的方法是使用PowerShell的-contains
运营商具有对直接阵列的工作和做的情况下,insenstive比较例如为:
if ($s -contains 'expired') { ... }
哇,我可以发誓我累了。我现在感觉很傻,谢谢凯斯,那也很好。 w00t。 – xbnevan 2010-06-01 14:59:09
简单而重要。正是我需要的。我正在开发一个PS 3系统,然后试图在PS 2上运行我的代码。我得到了这个错误,这是一个简单的解决方案来解决这个问题。 – 2013-01-08 13:58:00
由于克里斯的好处!这绝对让我朝着正确的方向前进。工作脚本: $ S = @(调用-SQLCMD -Query “USE数据库 GO EXEC Monitor_TEST_ps 'EXPORT_RUN',NULL,20”' -ServerInstance “testdb002 \ testdb_002”) 如果($ S | {? $ _ ['Status'] -eq'OK'}) { Write-Host“Expired found,FAIL。” } else { 写主机“未找到,确定”。 } – xbnevan 2010-05-28 17:51:55