问题
I am using this below script in Powershell (Version is 5.1):
Get-Content -Path path\to\text\file\to\be\read.txt -Wait
Now this continues to read even after the file is getting no update. How can I stop after I find particular line in the text file? Is there any other way to stop this on condition?
回答1:
You can pipe the output and use foreach to check each line, if the line equals a certain string you can use break
to stop the command:
Get-Content path\to\text\file\to\be\read.txt -wait | % {$_ ; if($_ -eq "yourkeyword") {break}}
For example, if you run the command above and do the following in another shell:
"yourkeyword" | Out-File path\to\text\file\to\be\read.txt -Append
The Get-Content
displays the new line and stops.
Explanation:
| %
- foreach line that is in the file or gets added to the file while the function runs
$_;
- first write out the line of the foreach then do another command
if($_ -eq "yourkeyword") {break}
- if the line of the foreach is equal to the keyword/line you want, stop the Get-Content
回答2:
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.'
Note that the -match operator performs substring matching using regexes (about_Regular_Expressions).
Read on for why the dummy do
loop is needed.
Paxz's answer is on the right track, but it tries to use break
(in isolation) to exit the pipeline, which (typically) terminates the whole script (if you submit the pipeline as a single command interactively, you may not notice).
break
/ continue
are designed to exit / continue loops (for
, foreach
, do
, while
, and switch
statements[1]), not pipelines.
As of PowerShell [Core] 7.0, there is no direct way to exit a pipeline prematurely, though adding this feature is the subject of this long-standing feature request on GitHub; currently, only direct use of Select-Object
with -First
can exit a pipeline prematurely, through use of non-public exception; while return
can be used in a ForEach-Object
script block, it only exits the current script-block invocation while continuing to process additional pipeline input.
If you use break
or continue
, PowerShell will look for any enclosing loop and if there is none, the script as a whole exits.
However, if you wrap a dummy loop around your pipeline[2], as shown above - whose sole purpose is to provide something for break
to break out of - execution continues, as (usually) desired.
Caveat:
break
/ continue
(and throw
) have an important side effect: they do not give the other commands participating in the pipeline a chance to exit normally; that is, their end
blocks / EndProcessing()
methods are not called, which can be problematic in two respects:
Cmdlets that need to clean up (dispose of) temporarily held resources do not get to clean up.
Aggregating cmdlets - those that of necessity collect all input before being able to produce output - never get to produce output; here's a simple example:
PS> do { 5..1 | % { $_; if ($_ -eq 3) { break } } | Sort-Object } while ($false)
# !! NO OUTPUT, because Sort-Object's EndProcessing() method was never called.
[1] When you examine a single value with a switch statement, break
exits the statement, as you would expect. If an array (a collection) of values is being processed, break
too exits the statement immediately, without processing further elements in the array; continue
, by contrast, continues processing with the next element.
[2] Another option is to use throw
to generate a script-terminating error that you catch by enclosing the pipeline in a try / catch statement, as shown in this answer. However, this has the side effect of recording an entry in the automatic $Error
collection, even though conceptually no actual error occurred.
来源:https://stackoverflow.com/questions/51981048/how-to-stop-get-content-wait-after-i-find-a-particular-line-in-the-text-file-us