解析输出并计算字符串出现的次数 [英] parse output and count number of times a string appears

查看:94
本文介绍了解析输出并计算字符串出现的次数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在运行一些代码.由于复杂性和冗长性,我认为也许可以使用一些代码来简化我的生活.因此,代码正在使用>commandA

I have some code running. Because of the complexity and the length I thought maybe use some code to make my life easy. So the code is running using >commandA

output
results
are
popping
...
here

我想计算bananacommandA输出(正在运行)中出现的次数,当计数为10时,我想停止处理(使用 CTRL + Z )和

I want to count the number of times banana appears in the output of commandA (which is running) and when the count is 10, I want to stop the processing (using CTRL+Z) and

echo "************we reached 10**********************"

然后重新开始.

我正在unix系统上的perl中编写代码.

I am writing the code in perl on unix system.

我不能在这里使用grep函数,因为该命令已经运行.或将运行,但没有grep函数.在命令运行之前,我将打开程序以在终端输出中查找特定的单词.现在使用grep非常容易,但是我不知道perl中的哪个函数实际上将输出作为stdin接收到终端

I cannot use grep function here as the command has already run. Or will be run but without a grep function. Before the command runs, I will turn on my program to look for the specific words in the terminal output. Now it would very easy to use grep, but I don't know which function in perl actually takes in the output to the terminal as stdin

推荐答案

您可以通过 open 将管道从管道连接到Perl程序,然后逐行读取其输出,直到达到终止条件为止:

You can start the other program by opening a pipe from it to your Perl program, and then read its output line by line until you reach the terminating condition:

open my $pipe, 'commandA |'
    or die "Error opening pipe from commandA: $!\n";

my $n = 0;
while (<$pipe>) {
    $n++ if /banana/;
    last if $n >= 10;
}
close $pipe;  # kills the command with SIGPIPE if it's not done yet

print "commandA printed 'banana' ", ($n >= 10 ? "at least 10" : $n), " times.\n";

不过,这里有两个陷阱要注意.一个是关闭管道只会在下一个尝试打印某些内容时杀死另一个程序.如果另一个程序可能长时间运行而不产生任何输出,则可能需要 kill 明确显示.

There are a couple of pitfalls to note here, though. One is that closing the pipe will only kill the other program when it next tries to print something. If the other program might run for a long time without generating any output, you may want to kill it explicitly.

为此,您将需要知道其进程ID,但是方便地,这正是打开管道时open返回的内容.但是,您可能希望使用open的多参数版本,以便返回的PID是实际commandA进程的PID,而不是用于启动它的shell的PID:

For this, you will need to know its process ID, but, conveniently, that's exactly what open returns when you open a pipe. However, you may want to use the multi-arg version of open, so that the PID returned will be that of the actual commandA process, rather than of a shell used to launch it:

my $pid = open my $pipe, '-|', 'commandA', @args
    or die "Error opening pipe from commandA: $!\n";

# ...
kill 'INT', $pid;  # make sure the process dies
close $pipe;

另一个陷阱是输出缓冲.大多数程序实际上并没有将其输出直接直接发送到输出流,而是会对其进行缓冲,直到累积了足够多或显式刷新了缓冲区为止.您通常不会注意到的原因是,默认情况下,许多程序(包括Perl)会在每行输出的末尾(即,每当打印\n时)刷新其输出缓冲区. if 他们检测到输出流进入交互式终端(即tty).

Another pitfall is output buffering. Most programs don't actually send their output directly to the output stream, but will buffer it until enough has accumulated or until the buffer is explicitly flushed. The reason you don't usually notice this is that, by default, many programs (including Perl) will flush their output buffer at the end of every output line (i.e. whenever a \n is printed) if they detect that the output stream goes to an interactive terminal (i.e. a tty).

但是,当将一个程序的输出通过管道传输到另一个程序时,第一个程序使用的I/O库可能会注意到输出流向管道而不是tty,并且可能会启用更积极的输出缓冲.通常这不会有问题,但是在某些有问题的情况下,这可能会在其他程序打印字符串的时间与您的程序收到字符串的时间之间增加相当大的延迟.

However, when you pipe the output of a program to another program, the I/O libraries used by the first program may notice that the output goes to a pipe rather than to a tty, and may enable more aggressive output buffering. Often this won't be a problem, but in some problematic cases it could add a substantial delay between the time when the other programs prints a string and the time when your program receives it.

不幸的是,如果您不能修改其他程序,那么您可以很轻松地做到这一点. 可以用称为"pseudo-tty"的管道替换管道,该管道看起来像是另一个命令的交互式终端,但是有点复杂.不过,有一个CPAN模块可以简化它,称为 IO :: Pty

Unfortunately, if you can't modify the other program, there's not much you can easily do about this. It is possible to replace the pipe with something called a "pseudo-tty", which looks like an interactive terminal to the other command, but that gets a bit complicated. There's a CPAN module to simplify it a bit, though, called IO::Pty.

(如果您可以修改其他程序,则容易得多.例如,如果它是另一个Perl脚本,则只需在脚本的开头添加$| = 1;即可启用输出自动刷新功能. )

(If you can modify the other program, it's a lot easier. For example, if it's another Perl script, you can just add $| = 1; at the beginning of the script to enable output autoflushing.)

这篇关于解析输出并计算字符串出现的次数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆