2010-05-28 75 views
6

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." 
} 

回答

5

您看到该方法的原因是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的任何)?)

+0

由于克里斯的好处!这绝对让我朝着正确的方向前进。工作脚本: $ 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

7

简单地说,$ s是一个.NET数组重新使用@()确保),并且您试图调用此.NET类型中不存在的方法(Contains)。

解决您的问题,最简单的方法是使用PowerShell的-contains运营商具有对直接阵列的工作和做的情况下,insenstive比较例如为:

if ($s -contains 'expired') { ... } 
+0

哇,我可以发誓我累了。我现在感觉很傻,谢谢凯斯,那也很好。 w00t。 – xbnevan 2010-06-01 14:59:09

+1

简单而重要。正是我需要的。我正在开发一个PS 3系统,然后试图在PS 2上运行我的代码。我得到了这个错误,这是一个简单的解决方案来解决这个问题。 – 2013-01-08 13:58:00

相关问题