Powershell 在字符串中搜索具有特殊字符的子字符串

Powershell 在字符串中搜索具有特殊字符的子字符串,powershell,substring,string-matching,Powershell,Substring,String Matching,我正在搜索字符串中包含特殊字符的子字符串。如何在字符串中搜索子字符串 $path = 'c:\test' $mountpoint = 'c:\test\temp\20190987-120\' 我想在$mountpoint中搜索$path 我试过使用-match,-contains,-in等 PS C:\>$path = 'c:\test' PS C:\>$mountpoint = 'c:\test\temp\20190987-120\' PS C:\>$path -conta

我正在搜索字符串中包含特殊字符的子字符串。如何在字符串中搜索子字符串

$path = 'c:\test'
$mountpoint = 'c:\test\temp\20190987-120\'
我想在
$mountpoint
中搜索
$path

我试过使用
-match
-contains
-in

PS C:\>$path = 'c:\test'
PS C:\>$mountpoint = 'c:\test\temp\20190987-120\'
PS C:\>$path -contains $mountpoint
False

在这种特殊情况下,可以使用
-Match

$mountpoint -match [regex]::escape($path)
这里的问题是
\
字符。它是正则表达式模式中的特殊字符,需要转义。由于
-Match
运算符进行正则表达式匹配,因此需要考虑特殊字符。我选择在这个场景中使用
Escape()
方法。您可以使用
\
字符单独转义字符,如
c:\\test
。评论重申了这一观点

使用正则表达式匹配,您可以控制要进行多少匹配。你可以加入锚和其他特殊角色来定制你的比赛。是测试和了解regex的众多在线选项之一

如果在下面的示例中注意到,匹配返回True。这是因为字符串
c:\test
存在于
c:\testing
中,这可能会给您带来不想要的结果。你需要仔细考虑这些情况。

"c:\testing" -match [regex]::Escape("c:\test")
True
-Contains
-in
是包含运算符。其目的是检查对象值集合中是否存在单个对象值。例如,当您想将单个字符串(如
'c:\test'
与集合(如
'c:\test'、'c:\folder'、'c:\folder\test'
进行比较时,最好使用这些字符串。它们获取您正在测试的值,基本上对集合中的每个项目执行
-eq
比较(不是字面上的比较,而是更有效的比较)。但是,您可以比较集合,但整个测试集合必须作为引用集合中的元素存在。使用
-Contains
,您希望参考集合位于操作员的左侧。使用中的,您希望参考集合位于操作员的右侧

使用-Contains和-In的示例

$collection = 'c:\test','c:\folder','c:\folder\test'
$path = 'c:\test'

$collection -contains $path
True

$path -in $collection
True

"c:\test\" -in $collection
False
请注意上一个示例中的假返回,因为尾部的
\
字符使其与集合中的任何元素都不同


有关
-Match
的信息,请参阅,有关
Escape()
方法的详细信息,请参阅。

在这种特殊情况下,您可以使用
-Match

$mountpoint -match [regex]::escape($path)
这里的问题是
\
字符。它是正则表达式模式中的特殊字符,需要转义。由于
-Match
运算符进行正则表达式匹配,因此需要考虑特殊字符。我选择在这个场景中使用
Escape()
方法。您可以使用
\
字符单独转义字符,如
c:\\test
。评论重申了这一观点

使用正则表达式匹配,您可以控制要进行多少匹配。你可以加入锚和其他特殊角色来定制你的比赛。是测试和了解regex的众多在线选项之一

如果在下面的示例中注意到,匹配返回True。这是因为字符串
c:\test
存在于
c:\testing
中,这可能会给您带来不想要的结果。你需要仔细考虑这些情况。

"c:\testing" -match [regex]::Escape("c:\test")
True
-Contains
-in
是包含运算符。其目的是检查对象值集合中是否存在单个对象值。例如,当您想将单个字符串(如
'c:\test'
与集合(如
'c:\test'、'c:\folder'、'c:\folder\test'
进行比较时,最好使用这些字符串。它们获取您正在测试的值,基本上对集合中的每个项目执行
-eq
比较(不是字面上的比较,而是更有效的比较)。但是,您可以比较集合,但整个测试集合必须作为引用集合中的元素存在。使用
-Contains
,您希望参考集合位于操作员的左侧。使用中的,您希望参考集合位于操作员的右侧

使用-Contains和-In的示例

$collection = 'c:\test','c:\folder','c:\folder\test'
$path = 'c:\test'

$collection -contains $path
True

$path -in $collection
True

"c:\test\" -in $collection
False
请注意上一个示例中的假返回,因为尾部的
\
字符使其与集合中的任何元素都不同

有关
-Match
的信息,请参阅,有关
Escape()
方法的更多详细信息,请参阅。

很有帮助,但我发现自己希望以不同的方式构建内容

  • 您正在寻找一种执行文本子字符串搜索的方法,该搜索定位在开头,仅在PowerShell中间接支持。有关解决方案,请参阅下一节

  • 运算符
    -contains
    -in
    与子字符串匹配无关(尽管
    -contains
    和.NET方法在名称上相似)

    • 它们通过元素对元素的相等性比较(隐含
      -eq
      )来测试集合中单个值的成员资格(作为一个整体包含)。有关详细信息,请参见的和的底部部分

    • 如果您想将这两项任务结合起来—在集合的所有元素中查找子字符串—您可以利用以下事实:PowerShell的
      -match
      -like
      操作符—如下所述—也可以对集合值的LHS进行操作,在这种情况下,它们充当过滤器;虽然这与会员资格测试并不完全相同,但它可以有效地用于此;演示如何以这种方式使用
      -match


解决: 使用.NET框架:

.NET方法执行文本子字符串搜索并返回
# Manual escaping: \ is doubled.
# Note the ^ to anchor matching at the start.
PS> 'foo\bar' -match '^foo\\'
True
# Programmatic escaping via [regex]::Escape()
# Note the ^ to anchor matching at the start.
PS> $s = 'foo\'; 'foo\bar' -match ('^' + [regex]::Escape($s))
True
# OK, because 'foo\' contains none of: ? * [
PS> 'foo\bar' -like 'foo\*'
True

# With a variable, using an expandable string:
PS> $s = 'foo\'; 'foo\bar' -like "$s*"
True
PS> $s = 'foo['; 'foo[bar' -like ([WildcardPattern]::Escape($s) + '*')
True