31

I am studying PowerShell. I want to know how to check if a string contains any substring in an array in PowerShell. I know how to do the same in Python. The code is given below:

any(substring in string for substring in substring_list)

Is there similar code available in PowerShell?

My PowerShell code is given below.

$a = @('one', 'two', 'three')
$s = "one is first"

I want to validate $s with $a. If any string in $a is present in $s then return True. Is it possible in PowerShell?

8 Answers 8

33

Using the actual variables in the question for simplicity:

$a = @('one', 'two', 'three')
$s = "one is first"
$null -ne ($a | ? { $s -match $_ })  # Returns $true

Modifying $s to not include anything in $a:

$s = "something else entirely"
$null -ne ($a | ? { $s -match $_ })  # Returns $false

(That's about 25% fewer characters than chingNotCHing's answer, using the same variable names of course :-)

Sign up to request clarification or add additional context in comments.

2 Comments

I like this answer, it's short, it's sweet, it works. I think that there just needs some explaination for understanding what is happening. After reading chingNotCHing's answer, I understood it a little better.
Instead of contains, I want to replace all array elements if contained in a string. I would use: $neu=(',','.' |%{ 'abc,.'.replace($_,'')}), but does not work because it repeats the string: abc. abc,
17
($substring_list | %{$string.contains($_)}) -contains $true

should strictly follow your one-liner

1 Comment

Best answer because it does not struggle on any unexpected regex-characters.
14

For PowerShell ver. 5.0+

Instead of,

$null -ne ($a | ? { $s -match $_ })

try this simpler version:

$q = "Sun"
$p = "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"
[bool]($p -match $q)

This returns $True if substring $q is in the array of string $p.

Another Example:

if ($p -match $q) {
    Write-Host "Match on Sun !"
}

4 Comments

This should be the correct answer at this point. Thanks for sharing.
This is backwards. The question is about substrings of $q not $p.
Vimes is right. The question is how you search elements of an array in a string. This answer is showing how to search for a string in the elements of an array. It's the opposite. Downvoted.
But @Michael Koza answered the question I have. ;)
11

I'm amazed that in 6 years nobody has given this more simple and readable answer

$a = @("one","two","three")
$s = "one1 is first"

($s -match ($a -join '|')) #return True

So simply implode the array into a string using vertical bar "|" , as this is the alternation (the "OR" operator) in regex. https://www.regular-expressions.info/alternation.html https://blog.robertelder.org/regular-expression-alternation/

Also keep in mind that the accepted answer will not search for exact match. If you want exact match you can use the \b (word boundary) https://www.regular-expressions.info/wordboundaries.html

$a = @("one","two","three")
$s = "one1 is first"

($s -match '\b('+($a -join '|')+')\b') #return False

2 Comments

It work !!!!!!!
Note this will work until the strings you are searching for contain special regex characters like $, ( or even .
7

Michael Sorens' code answer works best to avoid the pitfall of partial substrings matching. It just needs a slight regex modification. If you have the string $s = "oner is first", the code would still return true since 'one' would match 'oner' (a match in PowerShell means the second string contains the first string.

$a = @('one', 'two', 'three')
$s = "oner is first"
$null -ne ($a | ? { $s -match $_ })  # Returns $true

Add some regex for word boundary '\b' and the r on 'oner' will now return false:

$null -ne ($a | ? { $s -match "\b$($_)\b" })  # Returns $false

Comments

3

(I know it's an older thread but at least I might help people looking at this in the future.)

Any response given that uses -match will produce incorrect answers. Example: $a -match $b will produce false negatives if $b is "."

A better answer would be to use .Contains - but it's case sensitive so you'd have to set all strings to upper or lower case before comparing:

$a = @('one', 'two', 'three')
$s = "one is first"
$a | ForEach-Object {If ($s.toLower().Contains($_.toLower())) {$True}}

Returns $True

$a = @('one', 'two', 'three')
$s = "x is first"
$a | ForEach-Object {If ($s.toLower().Contains($_.toLower())) {$True}}

Returns nothing

You could tweak it to return $True or $False if you'd want, but IMO the above is easier.

Comments

1

It is possible to select a subset of strings containing any of the strings like this:

$array = @("a", "b")
$source = @("aqw", "brt", "cow")

$source | where { 
    $found = $FALSE
    foreach($arr in $array){
        if($_.Contains($arr)){
            $found = $TRUE
        }
        if($found -eq $TRUE){
            break
        }
    }
    $found
  }

Comments

1

One way to do this:

$array = @("test", "one")
$str = "oneortwo"
$array|foreach {
    if ($str -match $_) {
        echo "$_ is a substring of $str"
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.