stringpowershellstring-matching

How can i check if a string contains another string in powershell?


I have a string that is returned from an api call , the string is something like

       ".\controllers\myaction   c:\test\path"

I want to use Powershell to check if the string contains c:\

How can i do this ?

I have tried the following:

# if $result is populated with the string above then i do 

if ($result.context.ToLower().Contains("c:\") -eq "True")
{
      #code here
}

how can i do this ?


Solution

  • To complement helpful answer from Prateekshit Jaiswal with the truth about the -eq "True":

    if it really concerns "a string that is returned from an api call", the extra -eq "True" is not an issue:
    (although I would really recommend against adding that.)

    if (".\controllers\myaction   c:\test\path".ToLower().Contains("c:\") -eq "True") {
        Write-Host 'code here'
    }
    code here
    

    This is because PowerShell is a loosely typed language where the left-hand-side (LHS) of the condition dictates the comparison method. This means if the LHS is a boolean:

    ".\controllers\myaction   c:\test\path".ToLower().Contains("c:\") -is [Bool]
    True
    

    The RHS is type casted to a Boolean:

    [Bool]"True"
    True
    

    Because both sides are $True, the condition is simply considered $True (or truthy).

    So what's really playing here?

    I suspect that $result.context isn't really a string but something like an array of strings:

    $result = @{ context = ".\controllers\myaction", "c:\test\path" }
    $result.context
    .\controllers\myaction
    c:\test\path
    

    Or :

    "$($result.context)"
    .\controllers\myaction c:\test\path
    

    PowerShell's member-access enumeration is a nice feature but often makes things rather confusing:

    if you use the .ToLower() (string) method on a string array, this will work wonder well:

    $result.context.ToLower()
    .\controllers\myaction
    c:\test\path
    

    But as the .Contains method is also a method of an array, you might see unexpected results for this method:

    $result.context.ToLower().Contains("c:\")
    False
    

    This is because the array doesn't contain the (full) string "c:\". Where it does contain the string:

    $result.context.ToLower().Contains("c:\test\path")
    True
    

    Note that there is actually no reason to use the .ToLower() method here as by default PowerShell does a case-insensitive compare. Yet, this .ToLower() method might make things even more confusing as it "unrolls" any array with a single item to the item itself:

    @{ context = @("c:\test\path") }.context.GetType().Name
    Object[]
    

    vs:

    @{ context = @("c:\test\path") }.context.ToLower().GetType().Name
    String
    

    Which explains any unexpected result towards:

    @{ context = @("c:\test\path") }.context.Contains("c:\")
    False
    

    vs:

    @{ context = @("c:\test\path") }.context.ToLower().Contains("c:\")
    True
    

    Unfortunately, I can't give you an exact answer as I don't know the actual data type and structure of $result.context (you might consider to add the results of $result.context.GetType().Name and $result.context | ConvertTo-Json -Depth 9 to your question) but I hope that this might clear a few things with regards to the behavior of PowerShell related to your issue.