我陷入了从文件中提取文本的问题。这是我最终想要做的:
这是我正在研究的部分的片段:
$FileContents = Select-String -Path "C:\Users\me\Documents\file.ini" -Pattern "NoRequest"
使用该行时,我得到以下信息:
PS> $FileContents Documents\file.ini:222:NoRequest = false Documents\file.ini:281:NoRequest = false Documents\file.ini:347:NoRequest = false Documents\file.ini:387:NoRequest = false Documents\file.ini:1035:NOREQUEST = true Documents\file.ini:1047:NoRequest = true Documents\file.ini:1160:NOREQUEST = true Documents\file.ini:1242:NOREQUEST = true
这就是我想要得到的:
PS> $FileContents false false false false true true true true
我尝试将代码传递到Select-Object -Last 1
解决方案中,但是由于我的变量是数组,因此它选择数组中的最后一行,而不是每行的最后一个字。我还考虑过仅使用数组并执行“数组中的foreach行,除最后一个单词外的所有内容”。我猜想这会起作用,但是似乎这将是一个笨拙的解决方案。我敢肯定有一个简单有效的解决方案,但是我只是没有看到它。
答案 0 :(得分:4)
您可以在字符串上使用-split
并获取最后一个结果:
Select-String -Path "C:\Users\me\Documents\file.ini" -Pattern "NoRequest" |ForEach-Object {
-split $_.Line |Select-Object -Last 1
}
答案 1 :(得分:3)
或者,您可以只读入文件,将其传递到Where
语句以查找所需的行,然后使用$Matches
自动变量。
$FileContents = Get-Content "C:\Users\me\Documents\file.ini" |
Where{$_ -Match 'NoRequest = (true|false)'} |
ForEach-Object { $Matches[1] }
答案 2 :(得分:1)
对于诸如*.ini
文件之类的小文件,可以使用表达式而不是管道,这是一个选项,它使解决方案既简洁又高效(PSv4 +语法):
(@(Get-content C:\Users\me\Documents\file.ini) -match 'NoRequest').ForEach({ (-split $_)[-1] })
@(Get-content C:\Users\me\Documents\file.ini)
将指定文件的行作为数组返回(@(...)
确保即使在其中恰好只有 1 行,也将返回数组文件)。
-match
,以 array 作为LHS,充当 filter 并仅返回与指定正则表达式匹配的那些元素。
然后,PSv4 + .ForEach()
方法作用于结果数组的元素,通过空格(-split
)将每个元素拆分为标记,并返回 last 令牌(-1
)。
顺便说一句:-split
operator(-split '...'
)的 unary 形式就像古老的awk
Unix utility默认情况下一样:令牌基于任何空格作为分隔符的非空运行,开头和结尾的空格被忽略。
答案 3 :(得分:0)
仅将正则表达式更改为(?<=NoRequest.* )(\w+)$
,以使其与一行中的最后一个单词匹配(\w+
是一个或多个单词字符,$
是一行的结尾)如果其前面带有字符串“ NoRequest”。 (?<=...)
是一个肯定的后置断言,它检查模式的存在而不会使其成为返回的匹配的一部分。然后扩展匹配的值。
$file = 'C:\Users\me\Documents\file.ini'
Select-String -Path $file -Pattern '(?<=NoRequest.* )(\w+)$' | ForEach-Object {
$_.Matches.Value
}
如果最后一个单词只能是“ true”或“ false”,则可以通过以下方式将\w+
替换为更具体的表达式:
Select-String -Path $file -Pattern '(?<=NoRequest.* )(true|false)$' | ForEach-Object {
$_.Matches.Value
}