我们有一个保留服务器数据库的应用程序-服务器名称和其他相关信息的列表。有时,我们需要以XML格式导出信息以通过Powershell脚本进行处理。 XML文件中的服务器名称可以采用简单(“ ServerXX”)或FQDN(“ ServerXX.abc.com”)格式。该脚本将搜索始终采用简单格式的服务器名称,并且搜索结果应包含与搜索名称匹配的所有简单和完整服务器名称。
主要搜索运算符(略有简化)如下所示:
$FoundServer = ($ServerList | Where {$_.Name -match $ServerName+"*"})
$ ServerList是字符串(服务器名称)的数组。看起来很简单,并且按预期工作。通常。
奇怪的是,有时脚本找不到某些FQDN。例如,如果文件中的FQDN为“ ServerXX.abc.com”,而我们正在搜索“ ServerXX”,则找不到FQDN。同时搜索其他名称按预期方式工作。调试脚本时,可以看到{}中的表达式实际上是"ServerXX.abc.com" -like "ServerXX*"
。一定是真的。但是结果搜索结果为空。更有趣的是,如果将搜索名称指定为“ ServerXX。”,“ ServerXX.a”或FQDN中的其他字母,则脚本会找到它。如果在没有域名的文件中指定了相同的服务器名称(以简单形式),则脚本将找到它。
嗯,甚至更令人费解的是,我们有两个已安装应用程序的实例,一个实例用于生产,另一个实例用于测试。测试之一包含一个较小的服务器数据库。如果我将生产实例中的“不可见”服务器名称添加到测试实例中并导出数据库,脚本将找到该名称而不会出现任何问题。
如果我将-like替换为-match,问题将消失。因此,这不是XML文件生成器的问题(这是另一个PS脚本,该脚本生成PSCustomObject并通过Export-CliXml导出它)。服务器名称中的某些不可见或非ANSI符号也不是问题。我还手动检查了XML文件的内容。它非常庞大(数十兆字节)且非常复杂,因此很难分析,但我没有发现任何明显的问题。 XML结构看起来正确。
我不了解这种随机行为。它可以某种方式与XML文件大小相关吗? PS内存不足或类似问题?我们使用Powershell v4。
答案 0 :(得分:1)
请注意,这个答案不是 解决方案,因为(截至撰写本文时)没有足够的信息来诊断您的问题;但是,您使用-like
和-match
运算符应该受到一些审查。
$_.Name -match $ServerName+"*"
(更简洁地说:$_.Name -match "$ServerName*"
)与$_.Name -like "$ServerName*"
相同:
-match
使用regular expressions (正则表达式),(也)匹配输入的部分 >,除非明确规定要匹配输入的开头(^
和/或结尾($
)。
-like
使用wildcard expressions ,它必须与输入整体 相匹配。
尽管正则表达式和通配符关系密切,但它们的语法和功能却有所不同;正则表达式功能更强大; (例如,匹配默认情况下不区分大小写):
... -like 'ServerXX*'
匹配以 ServerXX
开头的字符串,后跟零个或多个任意字符({{1} }。
*
,'ServerXX'
和'ServerXX.foo.bar'
都将返回'ServerXXY'
。 $true
与包含子字符串... -match 'ServerXX*'
的字符串匹配(仅一个 ServerX
!)输入中的任意位置 ,如果后跟零个或更多(X
)*
个字符,因为复制符号X
会修改前面的字符/子表达式。
*
和'ServerXX'
将返回'ServerXX.foo.bar'
,而$true
和'ServerX'
也将返回–在这种情况下是不希望的。如果您输入的是FQDN,请使用以下等效的两个表达式:
'fooServerXX'
如果服务器名称是通过变量 提供的,例如... -like 'ServerXX.*'
... -match '^ServerXX\.'
,在最简单的情况下,使用expandable string $ServerName
:
"..."
这对于服务器名称很好,因为不允许它们包含可能被误认为正则表达式/通配符元字符(具有特殊字符的字符)的字符。含义,例如... -like "$ServerName.*"
... -match "^$ServerName\."
。
通常,最安全的方法是显式转义 变量值以确保其 literal 使用,请注意,与正则表达式相比,在 regex 中需要这样做的可能性更大,因为正则表达式具有更多的元字符:
*
使用带有... -like ('{0}.*' -f [System.Management.Automation.WildcardPattern]::Escape($ServerName))
... -match ('^{0}\.' -f [regex]::Escape($ServerName))
的单引号模板字符串,format operator(-f
代表第一个RHS操作数),可以清楚地看出使用了哪些部分从字面上看,以及哪些部分作为转义的变量值进行拼接。