从 Select-String 中取出每行的最后一个单词
Taking the last word of each line from Select-String
我在从文件中提取文本时遇到问题。这是我最终想做的:
- 在特定文件中搜索短语 "NoRequest" 的实例。
- 只取NoRequest的值。即如果 NoRequest = true,那么它只会将 "true" 添加到数组,而不是整行。
- 对文件中的每个短语实例执行此操作。
这是我正在处理的部分的片段:
$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 line in the array, cut everything off except the last word"。我猜这会起作用,但它似乎是一个笨拙的解决方案。我确信有一个简单有效的解决方案,但我只是没有看到它。
您可以在字符串上使用 -split
并获取最后的结果:
Select-String -Path "C:\Users\me\Documents\file.ini" -Pattern "NoRequest" |ForEach-Object {
-split $_.Line |Select-Object -Last 1
}
或者,您可以只读入文件,将其传递给 Where
语句以查找所需的行,然后使用 $Matches
自动变量。
$FileContents = Get-Content "C:\Users\me\Documents\file.ini" |
Where{$_ -Match 'NoRequest = (true|false)'} |
ForEach-Object { $Matches[1] }
对于 *.ini
文件之类的小文件,使用 表达式 而不是管道是一种选择,它可以实现既简洁又高效的解决方案(PSv4+ 语法):
(@(Get-content C:\Users\me\Documents\file.ini) -match 'NoRequest').ForEach({ (-split $_)[-1] })
@(Get-content C:\Users\me\Documents\file.ini)
returns 将指定文件的行作为一个数组(@(...)
确保返回一个数组,即使碰巧只有 1 文件中的行).
-match
,以 array 作为 LHS,充当 filter 和 returns 仅匹配指定正则表达式的那些元素。
PSv4+ .ForEach()
方法然后作用于结果数组的元素,通过空格将每个元素分成标记(-split
),并返回 last 标记 (-1
).
顺便说一句:-split
operator (-split '...'
) acts like the venerable awk
Unix utility 的 一元 形式默认执行:基于任何非空的 运行 空格作为分隔符来提取标记, 前导和尾随空格被忽略。
将您的正则表达式更改为 (?<=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
}
我在从文件中提取文本时遇到问题。这是我最终想做的:
- 在特定文件中搜索短语 "NoRequest" 的实例。
- 只取NoRequest的值。即如果 NoRequest = true,那么它只会将 "true" 添加到数组,而不是整行。
- 对文件中的每个短语实例执行此操作。
这是我正在处理的部分的片段:
$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 line in the array, cut everything off except the last word"。我猜这会起作用,但它似乎是一个笨拙的解决方案。我确信有一个简单有效的解决方案,但我只是没有看到它。
您可以在字符串上使用 -split
并获取最后的结果:
Select-String -Path "C:\Users\me\Documents\file.ini" -Pattern "NoRequest" |ForEach-Object {
-split $_.Line |Select-Object -Last 1
}
或者,您可以只读入文件,将其传递给 Where
语句以查找所需的行,然后使用 $Matches
自动变量。
$FileContents = Get-Content "C:\Users\me\Documents\file.ini" |
Where{$_ -Match 'NoRequest = (true|false)'} |
ForEach-Object { $Matches[1] }
对于 *.ini
文件之类的小文件,使用 表达式 而不是管道是一种选择,它可以实现既简洁又高效的解决方案(PSv4+ 语法):
(@(Get-content C:\Users\me\Documents\file.ini) -match 'NoRequest').ForEach({ (-split $_)[-1] })
@(Get-content C:\Users\me\Documents\file.ini)
returns 将指定文件的行作为一个数组(@(...)
确保返回一个数组,即使碰巧只有 1 文件中的行).-match
,以 array 作为 LHS,充当 filter 和 returns 仅匹配指定正则表达式的那些元素。PSv4+
.ForEach()
方法然后作用于结果数组的元素,通过空格将每个元素分成标记(-split
),并返回 last 标记 (-1
).
顺便说一句:-split
operator (-split '...'
) acts like the venerable awk
Unix utility 的 一元 形式默认执行:基于任何非空的 运行 空格作为分隔符来提取标记, 前导和尾随空格被忽略。
将您的正则表达式更改为 (?<=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
}