我正在用字符串中的特殊字符搜索子字符串。如何搜索字符串中的子字符串。
$path = 'c:\test'
$mountpoint = 'c:\test\temp\20190987-120\'
我要搜索$path
中的$mountpoint
我尝试使用-match
,-contains
,-in
等。
PS C:\>$path = 'c:\test'
PS C:\>$mountpoint = 'c:\test\temp\20190987-120\'
PS C:\>$path -contains $mountpoint
False
答案 0 :(得分:1)
在这种情况下,您可以使用-Match
。
$mountpoint -match [regex]::escape($path)
这里的问题是\
字符。它是正则表达式模式中的特殊字符,需要转义。由于-Match
运算符会进行正则表达式匹配,因此需要考虑特殊字符。在这种情况下,我选择使用Escape()
方法。您可以使用\
这样的c:\\test
字符分别转义字符。 LotPings条评论重申了这一想法。
使用正则表达式匹配,您可以控制要进行多少匹配。您可以包括锚点和其他特殊字符来定制您的比赛。 Regex101是测试和了解正则表达式的众多在线选项之一。
如果在下面的示例中注意到,匹配项将返回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
时,您希望参考集合位于操作员的LHS上。使用-in
,您希望引用集合位于操作员的RHS中。
使用-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
请注意最后一个示例中的False返回值,因为结尾的\
字符使它与集合中的任何元素都不同。
有关-Match
的信息,请参见About_Comparison_Operators,有关Escape()
方法的更多详细信息,请参见Regex.Escape Method。
答案 1 :(得分:0)
AdminOfThing's answer是有帮助的,但是我发现自己希望事物的框架不同。
您正在寻找一种执行文字子串搜索的方法,该搜索一开始是 ,即<在PowerShell中仅强支持间接 -有关解决方案,请参阅下一部分。
运算符 -contains
和-in
与 substring 匹配无关(尽管名称相似)在-contains
和String.Contains()
.NET方法之间)。
他们通过元素逐个方式在集合中测试单个值的成员身份(整体上包含 ) -元素平等比较(表示-eq
)。有关详细信息,请参见docs和this answer的底部。
如果要组合这两个任务-在集合的所有元素中查找子字符串-您可以利用PowerShell的-match
和{{ 1}}运算符-如下所述-也可以在 collection 值的LHS上进行运算,在这种情况下,它们可以充当 filters ;尽管这与测试成员资格并不完全相同,但可以有效地用于此; this answer展示了如何使用-like
。
使用.NET框架:
.NET String.IndexOf()
方法执行文字子字符串搜索,并返回子字符串在输入字符串中开始的字符的基于-match
的索引(和{{1 }}(如果根本找不到子字符串):
0
请注意,与PowerShell的运算符不同,以上默认情况下区分大小写 ,但是您可以使用其他参数更改为不区分大小写的行为:
-1
请注意,PowerShell在许多(但不是全部)上下文中使用不变而不是当前的区域性,例如在运算符 PS> 0 -eq 'foo\bar'.IndexOf('foo\')
True
, PS> 0 -eq 'foo\bar'.IndexOf('FOO\', [System.StringComparison]::InvariantCultureIgnoreCase)
True
,{{1}中}和-eq
语句。
如果不需要 anchor 您的子字符串搜索,即,如果您只想知道子字符串是否包含在输入字符串的 somewhere 中,则可以使用 String.Contains()
:
-contains
关于区分大小写的上述几点在这里也适用。
使用-in
运算符:
尽管switch
隐式执行 substring 匹配,但它是基于 regex (regular expression)而不是文字字符串来实现的。< / p>
PS> 'foo\bar'.Contains('oo\') #'# substring is present, but not at the start
True
默认执行不区分大小写的 匹配;使用-match
变体来区分大小写。
这意味着您可以方便地使用-match
(输入的开始锚点)来确保搜索表达式仅在输入字符串的开始处匹配。
相反,为了使您的搜索字符串在正则表达式中被视为 literal 字符串,您必须在其中-match
转义任何正则表达式元字符 (具有特殊含义的字符)在正则表达式中。
由于-cmatch
本身就是元字符,因此也必须转义,即^
。
在字符串文字中,您可以手动进行转义:
\
以编程方式,当字符串为变量时,必须使用\
方法:
\\
使用# Manual escaping: \ is doubled.
# Note the ^ to anchor matching at the start.
PS> 'foo\bar' -match '^foo\\'
True
运算符:
与[regex]::Escape()
不同,# Programmatic escaping via [regex]::Escape()
# Note the ^ to anchor matching at the start.
PS> $s = 'foo\'; 'foo\bar' -match ('^' + [regex]::Escape($s))
True
执行全字符串匹配,并且基于wildcard expressions(在Unix中又称为 glob 世界);尽管与正则表达式关系密切,但它们使用的是更简单,不兼容的语法(功能远不如以前那么强大)。
-like
默认执行不区分大小写的 匹配;使用-match
变体来区分大小写。
通配符只有3个基本结构,因此也只有3个元字符:-like
(匹配单个字符),-like
(匹配任意数量的字符,包括一个字符)和{{ 1}}(匹配单个字符的字符集或范围的开始,例如-clike
或?
)。
在最简单的情况下,您只需在搜索字符串后附加*
,以查看它是否与输入字符串的开头相符:
[
但是,与[a-z]
一样,可能需要以编程方式进行转义,这需要调用[45]
:
*