我在 Powershell 中使用以下脚本(版本为 5.1):
Get-Content -Path path\to\text\file\to\be\read.txt -Wait
现在,即使文件没有更新,它也会继续读取。 在文本文件中找到特定行后如何停止? 有条件的话还有其他方法可以阻止吗?
tl;博士
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
运算符使用正则表达式执行子字符串匹配(about_Regular_Expressions
)。
继续阅读为什么需要虚拟
do
循环。
Paxz 的答案是在正确的轨道上,但是它尝试使用
break
(隔离)来退出管道,这(通常)终止整个脚本[调用堆栈]; (如果您将管道作为单个命令交互式提交,您可能不会注意到)。
break
/ continue
旨在退出/继续 循环(for
、foreach
、do
、while
和 switch
语句[1]),而不是管道.
从 PowerShell [Core] 7.2.2 开始,没有直接的方法可以提前退出管道,尽管添加此功能是 GitHub 上这个长期存在的功能请求的主题;目前,只有直接使用 Select-Object
和
-First
才能通过使用非公共异常提前退出管道;虽然
return
可以在
ForEach-Object
脚本块中使用,但它仅退出当前脚本块调用,同时继续处理其他管道输入。
如果您使用 break
或
continue
,PowerShell 将查找任何封闭循环,并且 如果没有,则 整个脚本退出。 但是,
如果您在管道周围包裹一个虚拟循环[2],如上所示 - 其唯一目的是为break
提供一些东西来突破 -执行继续,如(通常)需要。
注意事项:
break
/
continue
(和
throw
)有一个重要的副作用:它们不会给参与管道的其他命令提供正常退出的机会;也就是说,它们的
end
块/
EndProcessing()
方法被不调用,这可能在两个方面存在问题:
无法清理。
Select-Object -First
与高级 PowerShell 函数/脚本一起使用(但不适用于(二进制)cmdlet,它可以通过实现
System.IDisposable
接口来确保清理),如下所示在 GitHub 问题 #7930 中讨论; GitHub PR #9900 旨在解决引入专用 cleanup
块的问题。
聚合 cmdlet - 在能够生成输出之前必须收集所有输入的 cmdlet - 永远不会生成输出;这是一个简单的例子:
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
语句检查
single值时,
break
会退出该语句,如您所料。如果正在处理值的数组(集合),
break
也会立即退出语句,不处理数组中的其他元素;相比之下,
continue
继续处理下一个元素。
[2] 另一种选择是使用 throw
生成脚本终止错误,您可以通过将管道包含在
try
/
catch
语句中来捕获该错误,如这个答案所示。 但是,这会产生在自动
$Error
集合中记录条目的副作用,即使概念上 没有发生实际错误。
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