【问题标题】:Grep filtering output from a process after it has already started?Grep 在已经启动后过滤进程的输出?
【发布时间】:2012-07-11 13:27:38
【问题描述】:

通常,当人们想要查看运行某项的特定输出行时,可以执行以下操作:

./a.out | grep IHaveThisString

但是如果 IHaveThisString 是每次都会改变的东西,所以你需要先运行它,观察输出以捕捉 IHaveThisString 在特定运行中的内容,然后 grep 出来怎么办?我可以只转储到文件,然后再转储 grep,但是否有可能做一些类似背景的事情,然后把它带到前台,然后把它带回来,但现在通过管道输送到一些 grep?类似于:

./a.out
Ctrl-Z
fg | grep NowIKnowThisString

只是想知道..

【问题讨论】:

  • 您是否尝试过使用./a.out > some_file,后来又使用tail -f some_file

标签: linux bash grep pipe


【解决方案1】:

不,如果你没有以其他方式保存它,它只会在你的屏幕缓冲区中。

【讨论】:

  • 我认为“以其他方式保存它”的机制将是问题的合法部分。
  • 在某些终端仿真器上,您可以随时启动跟踪。那是另一种方法,但它与会话本身无关。
【解决方案2】:

短格式:你可以这样做,但你需要知道你需要提前做;这不是事后可以交互式实施的东西。


编写脚本以确定字符串是什么。我们需要一个更详细的输出格式示例来提供更好的用法示例,但这里有一个用于整个第一行都是过滤器目标的简单情况:

run_my_command | { read string_to_filter_for; fgrep -e "$string_to_filter_for" }

用尽可能多的命令替换read string_to_filter_for,以读取足够多的输入以确定目标字符串是什么;如有必要,这可能是一个循环。

例如,假设输出包含以下内容:

Session id: foobar

然后,您想要 grep 查找包含 foobar 的行。

...那么您可以通过以下脚本进行管道传输:

re='Session id: (.*)'
while read; do
  if [[ $REPLY =~ $re ]] ; then
    target=${BASH_REMATCH[1]}
    break
  else
    # if you want to print the preamble; leave this out otherwise
    printf '%s\n' "$REPLY" 
  fi
done
[[ $target ]] && grep -F -e "$target"

如果您想手动指定过滤器目标,可以通过循环检查使用过滤器内容创建的文件,然后在启动 grep 时使用 that 来完成。

【讨论】:

    【解决方案3】:

    你需要的有点奇怪,但你可以这样做:

    • 你必须先进入script会话;
    • 那你平时怎么用shell;
    • 然后您开始并中断您的程序;
    • 然后在typescript 文件上运行grep

    例子:

    $ script
    $ ./a.out
    Ctrl-Z
    $ fg 
    $ grep NowIKnowThisString typescript
    

    【讨论】:

    • 据我了解,目标是让 grep 成为管道的一部分——因此,随着新输出的生成而持续进行,而不是仅在输出完成后才通过静态文件。在内容已经用完后,此处给出的内容不会继续通过 grep 发送新内容。
    • @CharlesDuffy:不,查尔斯,你不对。您在前台运行进程,这意味着您在进程完成后启动grep。唯一一点(据我所知)你想在没有grep 的情况下开始这个过程,当你在输出中看到一些有趣的东西时,你想grep 它。
    • 我不能同意这种解释。既定目标是能够“将过程带回前台”,现在过滤其输出。如果它在前台,显然它打算在此时仍在运行并生成新的输出。这使得我们试图完成的工作变得困难——但并非不可能。
    • 在 fg 之后,此时您无法将管道连接到它。所以它只是在终端运行。
    • @pizza 非常正确 - 但它可以通过管道进入配置为在运行时更改其行为的东西。
    【解决方案4】:

    您可以使用sed 等流编辑器来代替grep。这是我的意思的一个例子:

    $ cat list 
    Name to look for: Mike
    
    Dora 1
    John 2
    Mike 3
    Helen 4
    

    在这里,我们在第一行找到要查找的名称,并希望 grep 获取它。现在将命令传送到sed:

    $ cat list | sed -ne '1{s/Name to look for: //;h}' \
    > -e ':r;n;G;/^.*\(.\+\).*\n\1$/P;s/\n.*//;br'
    Mike 3
    

    注意:sed 本身可以将文件作为参数,但你不是在处理文本文件,所以这就是你使用它的方式。

    当然,您需要根据您的情况修改命令。

    【讨论】:

      猜你喜欢
      • 2018-09-09
      • 1970-01-01
      • 1970-01-01
      • 2016-02-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-02-05
      相关资源
      最近更新 更多