Почему не может я звонить Содержать метод от моего массива?

Arrrg! Я сталкиваюсь с тем, что я чувствую, немая проблема с простым сценарием, который я пишу в powershell. Я вызываю команду sql, которая называет сохраненный proc с результатами, я поместил его массив. Результаты выглядят примерно так:

Status                                       ProcessStartTime                            ProcessEndTime                             
------                                       ----------------                            --------------                             
Expired                                      May 22 2010  8:31PM                         May 22 2010  8:32PM

То, что я пытаюсь сделать, if($s.Contains("Expired")) , отчет перестал работать. Простой...?:( Проблема, с которой я сталкиваюсь, она похожа, Содержит метод, не загружается, поскольку я получаю ошибку как это:

Вызов метода перестал работать потому что [Система. Объект []] не содержит метод под названием, 'Содержит'. В line:1 char:12 + $s. Содержит <<<<("Истекший") + CategoryInfo: InvalidOperation: (Contains:String) [], 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." 
}
6
задан Keith Hill 29 May 2010 в 16:37
поделиться

2 ответа

Причина, по которой вы видите метод 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" (@ = это массив. )

Чтобы узнать, содержит ли массив элемент, вы можете использовать оператор -contains:

(9) C:\ -» @(1,2,3) -contains 1
True

Я думаю, у вас массив строк, поэтому вы можете использовать строковый литерал, например:

(10) C:\ -» @("Stuff","you've","got","might have","Expired") -contains "Expired"
True

Но если expired не является точным совпадением (вы искали элемент, содержащий expired, например "Connection Expired 1/1/2010"), вам нужно найти совпадения и проверить количество, я думаю:

(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 развернул его в строку. Придурок. Однако если совпадений больше одного, то:

(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

Поэтому вы можете проверить длину результатов, содержащих "Expired", чтобы узнать, есть ли среди них просроченные:

(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.

(может быть, у кого-то есть лучший способ проверить, содержит ли коллекция элемент, удовлетворяющий какому-то предикату (как Any в LINQ)?)

5
ответ дан 8 December 2019 в 18:33
поделиться

Проще говоря, $ s - это массив .NET (вы используете @ () , чтобы гарантировать это), и вы пытаетесь вызвать метод (Содержит) которого нет в этом типе .NET.

Самый простой способ решить вашу проблему - использовать оператор PowerShell -contains , который имеет преимущества работы с массивами напрямую и сравнения без учета регистра, например:

if ($s -contains 'expired') { ... }
8
ответ дан 8 December 2019 в 18:33
поделиться
Другие вопросы по тегам:

Похожие вопросы: