คุณจะทดสอบได้อย่างไรว่าวัตถุมีคุณสมบัติเฉพาะหรือไม่?


94

คุณจะทดสอบได้อย่างไรว่าวัตถุมีคุณสมบัติเฉพาะหรือไม่?

ขอบคุณที่ฉันทำได้ ...

$members = Get-Member -InputObject $myobject 

จากนั้นforeachผ่านทาง$membersแต่มีฟังก์ชันในการทดสอบว่าวัตถุมีคุณสมบัติเฉพาะหรือไม่?

ข้อมูลเพิ่มเติม: ปัญหาคือฉันกำลังนำเข้าไฟล์ CSV สองประเภทที่แตกต่างกันหนึ่งไฟล์มีสองคอลัมน์และอีกสามคอลัมน์ ฉันไม่สามารถรับเช็คเพื่อใช้กับ "พร็อพเพอร์ตี้" ได้เฉพาะกับ "NoteProperty" ... ไม่ว่าความแตกต่างคืออะไร

if ( ($member.MemberType -eq "NoteProperty" ) -and ($member.Name -eq $propertyName) ) 

6
($object.property -ne $null)เหรอ?
arco444

2
มันไม่สำคัญว่าถ้า propery ไม่อยู่ แต่มีความ$nullคุ้มค่า
แมตต์

1
@ arco444 ไม่ - ที่ต้องการคุณสมบัติที่มีอยู่เพื่อให้ประสบความสำเร็จ - หากคุณมีข้อมูลแบบไดนามิก (เช่นจากคำขอทางเว็บ) โดยที่บางแถวไม่ได้ระบุคุณสมบัตินั้นด้วยซ้ำการตรวจสอบนั้นจะล้มเหลว :(
BrainSlugs83

คำตอบ:


105

แบบนี้?

 [bool]($myObject.PSobject.Properties.name -match "myPropertyNameToTest")

16
คำตอบนี้ใช้ได้กับ powerShell v3 หรือสูงกว่าเท่านั้น สิ่งต่อไปนี้ควรใช้งานได้แม้กับ powerShell v2 ขึ้นไป: [bool] ($ file.psobject.Properties | โดยที่ {$ _. Name -eq "myPropertyNameToTest"})
Patrick

34
$myObject.PSobject.Properties.Name -contains "myPropertyNameToTest"จะดีกว่า. ไม่ต้องกังวลกับการจับคู่รูปแบบที่เป็นไปได้และคุณไม่จำเป็นต้องแคสต์เป็นบูลีน
Bacon Bits

2
เกิดอะไรขึ้นถ้าวัตถุที่มีคุณสมบัติThisisMyPropertyและคุณต้องการที่จะตรวจสอบMyProperty? คำตอบทั้งหมดในคำตอบนี้จะทำให้เกิดผลบวกลวง
ZoltánTamási

3
@KolobCanyon ซึ่งจะไม่ทำงานภายใต้โหมดเข้มงวด
user2864740

1
รหัสนี้จะให้ผลบวกเท็จหากตัวอย่างเช่นคุณที่ทดสอบ "Count" และวัตถุมีคุณสมบัติที่เรียกว่า "ThingCount"
dan-gph

72

คุณสามารถใช้ได้ Get-Member

if(Get-Member -inputobject $var -name "Property" -Membertype Properties){
#Property exists
}

12
คำตอบที่ดีที่สุด IMHO สิ่งนี้ใช้ได้กับวัตถุ. NET ที่ไม่มีสมาชิก PSobject นอกจากนี้เรายังสามารถลบตัวเลือก -Membertype ได้หากเราไม่สนใจว่าออบเจ็กต์มีสมาชิกประเภทใด - เพียงแค่ชื่อสมาชิกเท่านั้น มีประโยชน์มากกับวัตถุ Invoke-RestMethod หรือ ConvertFrom-Json!
Mister_Tom

2
ไวยากรณ์สั้น ๆ โดยไม่ต้องตรวจสอบประเภท: if($var | Get-Member Property){ }แม้จะสั้นกว่า แต่อ่านได้น้อย:if($var | gm Property){ }
zett42

นี่คือคำตอบที่ดีที่สุดในความคิดของฉัน
Kiran Hegde

25

สิ่งนี้รวบรัดและอ่านได้:

"MyProperty" -in $MyObject.PSobject.Properties.Name

เราสามารถใส่ไว้ในฟังก์ชัน:

function HasProperty($object, $propertyName)
{
    $propertyName -in $object.PSobject.Properties.Name
}

ฉันชอบคำตอบนี้ แต่ดูเหมือนว่าจะไม่ได้ผลในบางกรณีที่คำตอบของ CB ทำ
edwin

หรือโดยที่ "สั้น" = "ขยะที่ไม่จำเป็นนำมาใช้ผ่านโหมดเข้มงวดโดยไม่มีกรณีการใช้งานทางเลือกที่ดี" (เช่นไม่?.เทียบเท่า): | สิ่งนี้จะล้มเหลวสำหรับรูปแบบบางอย่างของ$MyObject$ null นั่นไม่ใช่กรณีของการผูกมัดโมฆะนอกโหมดเข้มงวด
user2864740

5

ฉันใช้สิ่งต่อไปนี้ซึ่งส่งคืนค่าคุณสมบัติเนื่องจากจะเข้าถึงผ่านทาง$thing.$propหาก "คุณสมบัติ" จะมีอยู่จริงและไม่เกิดข้อยกเว้นแบบสุ่ม หากคุณสมบัติ "ไม่มีอยู่" (หรือมีค่าว่าง) $nullจะถูกส่งกลับ: วิธีการนี้ทำหน้าที่ใน / มีประโยชน์สำหรับโหมดที่เข้มงวดเพราะงั้นก็จะจับพวกเขาทั้งหมด

ผมพบว่าวิธีนี้มีประโยชน์เพราะจะช่วยให้วัตถุที่กำหนดเอง PS วัตถุ .NET ปกติ PS HashTables และ .NET คอลเลกชันเช่นพจนานุกรมที่จะถือว่าเป็น "เป็ดพิมพ์เทียบเท่า"ซึ่งผมพบว่าเป็นแบบที่ดีเป็นธรรมสำหรับ PowerShell

แน่นอนว่านี่ไม่เป็นไปตามคำจำกัดความที่เข้มงวดของ "มีทรัพย์สิน" .. ซึ่งคำถามนี้อาจ จำกัด ไว้อย่างชัดเจน หากยอมรับคำจำกัดความที่ใหญ่กว่าของ "คุณสมบัติ" ที่สันนิษฐานไว้ที่นี่วิธีนี้สามารถแก้ไขได้เล็กน้อยเพื่อส่งคืนบูลีน

Function Get-PropOrNull {
    param($thing, [string]$prop)
    Try {
        $thing.$prop
    } Catch {
    }
}

ตัวอย่าง:

Get-PropOrNull (Get-Date) "Date"                   # => Monday, February 05, 2018 12:00:00 AM
Get-PropOrNull (Get-Date) "flub"                   # => $null
Get-PropOrNull (@{x="HashTable"}) "x"              # => "HashTable"
Get-PropOrNull ([PSCustomObject]@{x="Custom"}) "x" # => "Custom"
$oldDict = New-Object "System.Collections.HashTable"
$oldDict["x"] = "OldDict"
Get-PropOrNull $d "x"                              # => "OldDict"

และพฤติกรรมนี้อาจไม่เป็นที่ต้องการ [เสมอไป] .. กล่าวคือ มันเป็นไปไม่ได้ที่จะแยกแยะระหว่างและx.Countx["Count"]


ในการรับคุณสมบัติหรือ$nullไม่มีฟังก์ชันพิเศษ: $x = try{ $someObject.someProp } catch{ $null }. คุณสามารถละเว้น$nullจากcatchบล็อกได้ แต่ IMO จะช่วยเพิ่มความสามารถในการอ่าน
zett42


2

หากคุณใช้ StrictMode และ psobject อาจว่างเปล่ามันจะทำให้คุณมีข้อผิดพลาด

สำหรับวัตถุประสงค์ทั้งหมดสิ่งนี้จะทำ:

    if (($json.PSobject.Properties | Foreach {$_.Name}) -contains $variable)

1

จริงคล้ายกับการตรวจสอบจาวาสคริปต์:

foreach($member in $members)
{
    if($member.PropertyName)
    {
        Write $member.PropertyName
    }
    else
    {
        Write "Nope!"
    }
}

1
สิ่งนี้อาจใช้ไม่ได้หากคุณสมบัติมีค่า $ null จริงๆ
Tola Odejayi

8
สิ่งนี้จะล้มเหลวหาก PowerShell อยู่ในโหมดเข้มงวด
Ian Kemp

@IanKemp โหมดเข้มงวดคืออะไร? ชอบนโยบายการดำเนินการหรือไม่?
Kolob Canyon

1
@KolobCanyon docs.microsoft.com/en-za/powershell/module/... - หลักก็เทียบเท่า PS ถึง use strictJavaScript
Ian Kemp

1
สิ่งนี้จะใช้ไม่ได้เช่นกันหากคุณสมบัติมีอยู่และตั้งค่าเป็น $ false

1

เพียงเพื่อชี้แจงวัตถุต่อไปนี้

$Object

ด้วยคุณสมบัติดังต่อไปนี้

type        : message
user        : john.doe@company.com
text        : 
ts          : 11/21/2016 8:59:30 PM

ต่อไปนี้เป็นเรื่องจริง

$Object.text -eq $NULL
$Object.NotPresent -eq $NULL

-not $Object.text
-not $Object.NotPresent

ดังนั้นคำตอบก่อนหน้านี้ที่ตรวจสอบคุณสมบัติโดยใช้ชื่ออย่างชัดเจนจึงเป็นวิธีที่ถูกต้องที่สุดในการตรวจสอบว่าคุณสมบัตินั้นไม่มีอยู่


1

เพียงตรวจสอบกับค่าว่าง

($myObject.MyProperty -ne $null)

หากคุณไม่ได้ตั้งค่า PowerShell เป็น StrictModeสิ่งนี้จะใช้ได้แม้ว่าคุณสมบัตินั้นจะไม่มีอยู่:

$obj = New-Object PSObject;                                                   
Add-Member -InputObject $obj -MemberType NoteProperty -Name Foo -Value "Bar";
$obj.Foo; # Bar                                                                  
($obj.MyProperty -ne $null);  # False, no exception

2
เท่าที่ฉันเห็นสิ่งนี้ใช้ได้ถ้าคุณสมบัติมีอยู่และเป็น $ null แต่ไม่ใช่ถ้าคุณสมบัติไม่มีอยู่ - การพยายามเข้าถึงเพื่อทำการตรวจสอบ null จะทำให้เกิดข้อยกเว้น
Peter

@Peter คุณสามารถให้ตัวอย่างของการตรวจสอบโมฆะที่มีข้อยกเว้นเมื่อคุณสมบัติไม่มีอยู่ ฉันได้เพิ่มตัวอย่างที่ไม่มีคุณสมบัติและไม่มีข้อยกเว้น
Shaun Luttin

2
เรียกใช้สิ่งนี้: Set-Strictmode -version Latest;$obj = ConvertFrom-Json -InputObject '{"name":"test", "version":"1.1.0"}';If($obj.StartDate -ne $null){Write-Verbose -Message $obj.startDate -Verbose}และคุณจะได้รับข้อผิดพลาดคุณสมบัติไม่พบ 'StartDate' ในวัตถุนี้ อย่างไรก็ตามฉันต้องมีคุณสมบัติตามความคิดเห็นของฉัน - คุณจะไม่เข้าใจหากไม่ได้ตั้งค่า Strictmode ไว้ ฉันตั้งค่าไว้เสมอจึงไม่เคยตระหนักจนกว่าฉันจะทดสอบสิ่งนี้! ฉันคิดว่าคนส่วนใหญ่ใช้ (หรือควรใช้) 'Set-Strictmode'
Peter

2
น่าจะดีที่สุดถ้าคุณมีคุณสมบัติตามคำตอบและฉันจะลบการลงคะแนนของฉัน ทุกคนได้เรียนรู้บางสิ่งซึ่งเป็นประเด็น :-)
ปีเตอร์

0

ฉันลงเอยด้วยฟังก์ชั่นต่อไปนี้ ...

function HasNoteProperty(
    [object]$testObject,
    [string]$propertyName
)
{
    $members = Get-Member -InputObject $testObject 
    if ($members -ne $null -and $members.count -gt 0) 
    { 
        foreach($member in $members) 
        { 
            if ( ($member.MemberType -eq "NoteProperty" )  -and `
                 ($member.Name       -eq $propertyName) ) 
            { 
                return $true 
            } 
        } 
        return $false 
    } 
    else 
    { 
        return $false; 
    }
}

0

ฉันเพิ่งเปลี่ยนไปตั้งค่าโหมดเข้มงวด - เวอร์ชัน 2.0 และการทดสอบค่าว่างของฉันล้มเหลว

ฉันเพิ่มฟังก์ชั่น:

#use in strict mode to validate property exists before using
function exists {
  param($obj,$prop)
  try {
    if ($null -ne $obj[$prop]) {return $true}
    return $false
  } catch {
    return $false
  }
  return $false
}

ตอนนี้ฉันเขียนโค้ด

if (exists $run main) { ...

ค่อนข้างมากกว่า

if ($run.main -ne $null) { ...

และเรากำลังไป ดูเหมือนว่าจะทำงานกับวัตถุและแฮชแท็ก

เพื่อประโยชน์ที่ไม่ได้ตั้งใจก็คือการพิมพ์น้อยลง


สำหรับค่าว่างหรือว่างฉันมักจะใช้: IF ([string] :: IsNullOrEmpty ($ userID)) {write-host "Null or empty"}

0

ฉันแค่อยากจะเพิ่มในการสนทนาเพราะฉันเพิ่งใช้เวลาหลายชั่วโมงในการแก้ไขข้อบกพร่องของโค้ดที่ใช้งานได้

ตอบโดยCB. ทำงานได้ดีสำหรับการจับคู่ตัวแปรกับชื่อคุณสมบัติ (เป็นสตริง) ปัญหาเริ่มต้นเมื่อตัวแปรตรงกับส่วนหนึ่งของชื่อคุณสมบัติ

if([bool]($allFiles.PSobject.Properties.name -match $_.Name) -ne $true){

ต่อมาฉันใช้มันเพื่ออ้างถึงคุณสมบัติของวัตถุ แต่เนื่องจากมันจับคู่เพียงส่วนหนึ่งของคุณสมบัติอื่นดังนั้นจึงไม่มีคุณสมบัติจริงที่มีชื่อที่แน่นอนการดำเนินการจึงส่งคืนค่า 'null'

หลังจากนั้นฉันใช้โซลูชันที่เสนอโดยdan-gphซึ่งเรียบร้อยมาก:

if([bool]($_.Name -in $allFiles.PSobject.Properties.Name) -ne $true){

ซึ่งจะทำให้มั่นใจว่าทั้งสองมีค่าเหมือนกัน ฉันรู้ว่าต้องมองไปทางไหน แต่ก็ยังเจ็บปวดแม้จะรู้ว่าปัญหาคือหลายชื่อที่จับคู่สตริงกับ 2 ตัวอักษร คำนำหน้า แต่เหมือนกัน


-1

ฉันเพิ่งเริ่มใช้ PowerShell กับ PowerShell Core 6.0 (เบต้า) และใช้งานได้ดังนี้:

if ($members.NoteProperty) {
   # NoteProperty exist
}

หรือ

if (-not $members.NoteProperty) {
   # NoteProperty does not exist
}

1
ไม่อยู่ในโหมดเข้มงวด
Casper Leon Nielsen


-1

สำหรับการระบุว่าวัตถุใดในอาร์เรย์มีคุณสมบัติ

$HasProperty = $ArrayOfObjects | Where-Object {$_.MyProperty}

ล้มเหลวใน StrictMode เมื่อไม่มีคุณสมบัติ
user2864740
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.