在PowerShell中检查字符串是否包含数组中的任何子字符串

30

我正在学习PowerShell。我想知道如何检查字符串是否包含 PowerShell 数组中的任何子字符串。我知道如何在 Python 中执行相同的操作。以下是代码:

any(substring in string for substring in substring_list)

是否有类似的PowerShell代码可用?

以下是我的PowerShell代码。

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

我想用$a中的字符串验证$s。如果$a中的任何字符串存在于$s中,那么返回True。在PowerShell中是否有可能实现?

8个回答

33

为了简单起见,使用问题中的实际变量:

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

将 $s 修改为不包括 $a 中的任何内容:

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

(这比chingNotCHing的答案少了约25%的字符,当然变量名相同:-)


5
我喜欢这个答案,它简短、甜美且有效。我认为只需要一些解释才能理解正在发生的事情。阅读chingNotCHing的答案后,我更好地理解了它。 - Newteq Developer
不想使用contains方法,而是想要在字符串中替换所有包含的数组元素。我会这样做:$neu=(',','.' |%{ 'abc,.'.replace($_,'')}), 但是它不能正常工作,因为它会重复字符串:abc. abc, - Timo

17
($substring_list | %{$string.contains($_)}) -contains $true

应严格遵循您的一句话描述。


最佳答案是因为它不会在任何意外的正则表达式字符上出现问题。 - Carsten

13

对于 PowerShell 版本 5.0+

不再使用,

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

试试这个更简单的版本:

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

如果字符串数组$p中包含子字符串$q,则该函数返回$True

另一个例子:

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

1
这应该是目前正确的答案。谢谢分享。 - Mike Q
4
这是相反的。问题是关于$q的子字符串,而不是$p - Vimes
3
Vimes 是正确的。问题在于如何在字符串中搜索数组元素。这个答案展示了如何在数组元素中搜索字符串。这是相反的。被踩了。 - crisc2000
但是@Michael Koza回答了我提出的问题。 ;) - Tom A

8

我很惊讶六年来没有人给出更简单易懂的答案。

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

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

使用竖线 "|" 将数组简单地合并成字符串,因为这是正则表达式中的交替 (即 "OR" 运算符)。 参考链接: https://www.regular-expressions.info/alternation.html https://blog.robertelder.org/regular-expression-alternation/ 同时请注意,被接受的答案将不能进行精确匹配。 如果您想要精确匹配,可以使用 \b(单词边界)。 参考链接: https://www.regular-expressions.info/wordboundaries.html
$a = @("one","two","three")
$s = "one1 is first"

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

7
Michael Sorens的代码回答最能避免部分子字符串匹配的陷阱,只需要进行轻微的正则表达式修改。如果你有字符串$s = "oner is first",该代码仍然会返回true,因为'one'与'oner'匹配(在PowerShell中匹配意味着第二个字符串包含第一个字符串)。
$a = @('one', 'two', 'three')
$s = "oner is first"
$null -ne ($a | ? { $s -match $_ })  # Returns $true

添加一些单词边界正则表达式'\b',然后'oner'上的r现在会返回false:
$null -ne ($a | ? { $s -match "\b$($_)\b" })  # Returns $false

3
(我知道这是一个较旧的线程,但至少我可能会帮助未来查看此内容的人。)
任何使用-match给出的响应都会产生不正确的答案。 例如:$a -match $b如果$b为“。”,将产生假阴性。
更好的答案是使用.Contains-但它区分大小写,因此您必须在比较之前将所有字符串设置为大写或小写:
$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}}

不返回任何东西

如果您想要的话,可以将其调整为返回 $True 或 $False,但在我看来,上述方法更容易。


1
可以通过以下方式选择包含任何字符串的子集:
$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
  }

1
一种方法是这样做:


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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接