我正在使用Powershell来获取日志文件的内容。我试图提取两个已知单词之间的未知字符串。我需要对多行执行此操作,因此我想搜索并返回多个字符串。我看过很多例子,并尝试了不同的方法,但是它们没有用。
我已经使用reg ex将其范围缩小到我关心的日志中的行,但是我无法提取所需的文本。
$fails = Select-String -Path 'C:\Users\user\Documents\wsyncmgr.log' -Pattern "^(?=.*?\bError\b)(?=.*?\bSoftware\b)(?=.*?\bLicense\b)(?=.*?\bTerms\b)(?=.*?\bnot\b)(?=.*?\bdownloaded\b).*$"
这将返回:
C:\Users\user\Documents\wsyncmgr.log:7340:Failed to sync update 817ad2a6-3ca7-4fa2-aa32-9b906a2d9fdc. Error: The Microsoft Software License Terms have not been completely
downloaded and~~cannot be accepted. Source: Microsoft.UpdateServices.Internal.BaseApi.SoapExceptionProcessor.DeserializeAndThrow $$<SMS_WSUS_SYNC_MANAGER><10-23-2019
08:31:07.642+300><thread=5916 (0x171C)>
C:\Users\user\Documents\wsyncmgr.log:7341:Failed to sync update 87e13ecb-c669-43be-9e2a-01e567285031. Error: The Microsoft Software License Terms have not been completely
downloaded and~~cannot be accepted. Source: Microsoft.UpdateServices.Internal.BaseApi.SoapExceptionProcessor.DeserializeAndThrow $$<SMS_WSUS_SYNC_MANAGER><10-23-2019
08:31:07.643+300><thread=5916 (0x171C)>
等等。
我只想提取更新的唯一ID,这样我就可以将它们全部放入变量中,以后再使用。
我最近的是
$removeFirst = $fails -split "update "
$removeLast = $removeFirst -split ". Error:"
$removeLast[1]
C:\Users\user\Documents\wsyncmgr.log:7341:Failed to sync
87e13ecb-c669-43be-9e2a-01e567285031
The Microsoft Software License Terms have not been completely downloaded and~~cannot be accepted. Source: Microsoft.UpdateServices.Internal.BaseApi.SoapExceptionProcessor.DeserializeAndThrow $$<SMS_WSUS_SYNC_MANAGER><10-23-2019 08:31:07.643+300><thread=5916 (0x171C)>
C:\Users\user\Documents\wsyncmgr.log:7342:Failed to sync
c1a1ec21-8efc-4cd4-8e85-90a03fc7b0c8
The Microsoft Software License Terms have not been completely downloaded and~~cannot be accepted. Source: Microsoft.UpdateServices.Internal.BaseApi.SoapExceptionProcessor.DeserializeAndThrow $$<SMS_WSUS_SYNC_MANAGER><10-23-2019 08:31:07.644+300><thread=5916 (0x171C)>
C:\Users\user\Documents\wsyncmgr.log:7343:Failed to sync
09dc7113-fa44-4ca8-9d70-ec254d4d2f04
The Microsoft Software License Terms have not been completely downloaded and~~cannot be accepted. Source: Microsoft.UpdateServices.Internal.BaseApi.SoapExceptionProcessor.DeserializeAndThrow $$<SMS_WSUS_SYNC_MANAGER><10-23-2019 08:31:07.644+300><thread=5916 (0x171C)>
但这只会删除我指定的单词,并将其余的放在单独的行上。然后数组只返回我指定的行,但我要多个。我想消除“更新”之前的所有内容以及“。错误之后”的所有内容。 每行只保留“ 09dc7113-fa44-4ca8-9d70-ec254d4d2f04”。
使用正则表达式不好对任何帮助表示赞赏
答案 0 :(得分:1)
如果您的ID具有相同的结构,则可以执行以下操作:
$fails | Select-String '(?:[a-z0-9]+-){4}[a-z0-9]+' |
ForEach-Object { $_.Matches.Value }
说明:
(?:[a-z0-9]+-)
非捕获组,匹配一个或多个字母数字字符,并以-
结尾{4}
匹配四次[a-z0-9]+
匹配一个或多个字母数字字符。由于将捕获多行,因此每条匹配的行将是一个MatchInfo
对象。通过插入Foreach-Object
,我们可以像$_
一样访问每个对象。 .Matches.Value
将仅检索该对象的匹配值。
答案 1 :(得分:0)
在字符串上使用[regex]::matches
方法(必须提供正则表达式进行匹配),然后检查返回的数组以查找字符串中的每个特定匹配项。这是一个示例:
$myString = "The quick brown fox"
$myMatches = [regex]::matches($myString, "\w+")
$myMatches.Value
上面的示例在字符串中查找单词。 matches
方法匹配多次,而-match
运算符没有全局匹配选项(我发现,很可能会在这里被证明是错误的)。 .Value
属性包含实际匹配项,尽管您也可以在System.Text.RegularExpressions.Match
对象上使用其他有用的成员。
您的问题有点模棱两可:
我错过了第二部分,所以让我在这里解决。由于您要从字符串中选择已知模式(唯一ID),因此您可以 使用-match
运算符:
$fails | Foreach-Object {
if( $_ -match '[a-z0-9]{8}-([a-z0-9]{4}-){3}[a-z0-9]{12}') ){
$matches[0]
}
$matches
是一个特殊的数组,当使用-match
运算符进行匹配时,该匹配项将放入$matches
的0索引中。过去的每个指示捕获组匹配的索引,但是您在这里不需要。
我提供的表达式是针对格式正确的UUID的,应与MS regex引擎以及PCRE和Javascript一起使用。当然,请确保使用不区分大小写的匹配,或者在其他情况下根据需要添加大写字母变体。