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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.