我正在Powershell(版本为5.1)中使用以下脚本:
Get-Content -Path path\to\text\file\to\be\read.txt -Wait
现在,即使文件没有更新,此内容仍可继续读取。 在文本文件中找到特定行后如何停止? 还有其他方法可以阻止这种情况吗?
答案 0 :(得分:6)
tl; dr
do {
Get-Content -Path path\to\text\file\to\be\read.txt -Wait | ForEach-Object {
# Pass the input line through.
$_
# Exit once the string of interest is found.
if ($_ -match 'patternOfInterest') { break }
}
} while ($false) # dummy loop so that `break` can be used.
# NOTE: Without the dummy `do` loop, this code would not be reached.
'Line of interest found.'
请注意,-match
operator使用 regexes (about_Regular_Expressions
)执行 substring 匹配。
继续阅读为什么需要虚拟do
循环。
Paxz's answer处在正确的轨道上,但它试图(单独)使用break
来退出管道,(通常)终止整个脚本 (如果您以交互方式作为单个命令提交管道,则可能不会注意到)。
break
/ continue
旨在退出/继续循环(for
,foreach
,do
, while
和switch
语句 [1] ),而不是管道 。
从PowerShell [Core] 7.0开始,没有直接方法过早退出管道 ,尽管添加此功能是this long-standing feature request on GitHub的主题;当前,通过使用非公共异常,仅将Select-Object
与-First
直接使用才能过早退出管道;尽管return
可以在ForEach-Object
脚本块中使用,但它仅退出当前脚本块调用,同时继续处理其他管道输入。
如果使用break
或continue
,PowerShell将查找任何封闭循环,如果没有 ,<整个em>脚本退出。
但是,如果您将 dummy 循环包裹在管道中 [2] ,如上所示-其唯一目的是提供一些东西让break
脱离-(通常)按要求继续执行 。
注意事项:
break
/ continue
(和throw
)具有重要的副作用 :他们不给予其他参与管道的命令有机会正常退出 ;也就是说,它们的end
块/ EndProcessing()
方法被 not 调用,这在两个方面可能是有问题的:
需要清理(处置)临时保留的资源的cmdlet 不清理。
Select-Object -First
与高级PowerShell函数/脚本一起使用(但不适用于(二进制)cmdlet,这可以通过实现System.IDisposable
来确保清理)接口),如GitHub issue #7930中所述; GitHub PR #9900旨在解决引入专用cleanup
块的问题。聚合 cmdlet-那些必需的cmdlet必须先收集 all 个输入,然后才能产生输出-从不产生输出;这是一个简单的例子:
PS> do { 5..1 | % { $_; if ($_ -eq 3) { break } } | Sort-Object } while ($false)
# !! NO OUTPUT, because Sort-Object's EndProcessing() method was never called.
[1]当您使用switch
语句检查单个值时,break
会退出语句,这与您期望的一样。如果正在处理值的 array (集合),则break
也会立即退出该语句,不处理数组中的其他元素;相反,continue
将继续处理下一个元素。
[2]另一个选择是使用throw
生成脚本终止错误,您可以通过将管道包含在try
/ catch
statement中来捕获该错误,如this answer所示。但是,这会产生副作用,即使从概念上说没有实际的错误发生,也可以在自动$Error
集合中记录一个条目。
答案 1 :(得分:1)
您可以通过管道传输输出并使用foreach检查每一行,如果该行等于某个字符串,则可以使用break
停止命令:
Get-Content path\to\text\file\to\be\read.txt -wait | % {$_ ; if($_ -eq "yourkeyword") {break}}
例如,如果您运行上面的命令并在另一个shell中执行以下操作:
"yourkeyword" | Out-File path\to\text\file\to\be\read.txt -Append
Get-Content
显示新行并停止。
说明:
| %
-foreach行中的文件行或函数运行时添加到文件中的行
$_;
-首先写出foreach的行,然后执行另一个命令
if($_ -eq "yourkeyword") {break}
-如果foreach的行与所需的关键字/行相等,请停止Get-Content