使用 powershell 在文本文件中找到特定行后如何停止 Get-Content -wait?按需退出管道

问题描述 投票:0回答:2

我在 Powershell 中使用以下脚本(版本为 5.1):

Get-Content -Path path\to\text\file\to\be\read.txt -Wait

现在,即使文件没有更新,它也会继续读取。 在文本文件中找到特定行后如何停止? 有条件的话还有其他方法可以阻止吗?

powershell pipeline break powershell-5.0
2个回答
11
投票

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()
方法被
调用,这可能在两个方面存在问题:

  • 需要清理(处置)临时持有的资源的 Cmdlet

    无法清理

  • 聚合 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
 集合中记录条目的副作用,即使 
概念上 没有发生实际错误。


2
投票
您可以管道输出并使用 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

    

© www.soinside.com 2019 - 2024. All rights reserved.