【问题标题】:pipe tail output into another script管道尾输出到另一个脚本
【发布时间】:2012-08-22 18:56:02
【问题描述】:

我正在尝试将 tail 命令的输出通过管道传输到另一个 bash 脚本中进行处理:

tail -n +1 -f your_log_file | myscript.sh

但是,当我运行它时,$1 参数(在 myscript.sh 中)永远不会到达。我错过了什么?如何通过管道将输出作为脚本的输入参数?

PS - 我希望 tail 永远运行并继续将每一行通过管道传输到脚本中。

编辑 目前 myscripts.sh 的全部内容是:

echo $1;

【问题讨论】:

  • 您缺少要分配给 $1 的参数。管道将 tail 的输出连接到脚本的标准输入。您能否发布myscript.sh,或者至少足以确定您是否需要一个参数(以及该参数应该是什么),以及它将如何处理其标准输入上显示的数据。

标签: bash parameters pipe tail


【解决方案1】:

一般来说,这是处理脚本标准输入的一种方法:

#!/bin/bash

while read line; do
    echo $line
done

这是一个非常粗略的 bash,相当于 cat。它确实证明了一个关键事实:脚本中的每个命令都从 shell 继承其标准输入,因此您实际上不需要做任何特殊的事情来访问传入的数据。read 从 shell 获取输入,哪个(在您的情况下)从通过管道连接到它的tail 进程获取其输入。

作为另一个例子,考虑这个脚本;我们称之为“mygrep.sh”。

#!/bin/bash

grep "$1"

现在是管道

some-text-producing-command | ./mygrep.sh bob

行为与

相同
some-text-producing-command | grep bob

$1 如果你这样调用你的脚本就会被设置:

./myscript.sh foo

那么$1 的值为“foo”。

位置参数和标准输入是分开的;你可以这样做

tail -n +1 -f your_log_file | myscript.sh foo

现在标准输入仍来自tail 进程,$1 仍设置为 'foo'。

【讨论】:

  • 不确定我是否关注。 foo 是从哪里来/从哪里来的?
  • 'foo' 只是命令行上的任意字符串。如果你的命令后面有一个字符串,那就是分配给$1 的字符串。如果有第二个字符串,则将其分配给$2,依此类推。在您的原始示例中,myscript.sh 后面没有参数,这就是 $1 没有价值的原因。
  • 正确 - 那么如何将 tail 的输出通过管道传输到 myscript.sh 中?我只是将它合并到 myscript.sh 中吗?如果有,怎么做?
  • 脚本中任何从标准输入读取的命令都将从管道读取。在管道中运行我的答案顶部的示例脚本,看看它是如何工作的。
  • @chepner,对于 cat 等效项,循环应该有 echo "$line",而不是 echo -n "$line"
【解决方案2】:

也许您对awk 感到困惑?

tail -n +1 -f your_log_file | awk '{
    print $1
}'

将打印 tail 命令输出的第一列。

在shell中,也可以实现类似的效果:

tail -n +1 -f your_log_file | while read first junk; do
    echo "$first"
done

或者,您可以将整个 while ... done 循环放在 myscript.sh

【讨论】:

    【解决方案3】:

    管道将一个进程的输出 (stdout) 连接到另一个进程的输入 (stdin)。 stdin 与启动时发送给进程的参数不同。

    您要做的是将第一个进程的输出中的行转换为第二个进程的参数。这正是xargs 命令的用途。

    您需要做的就是在初始命令之间通过管道传递xargs,它就会起作用

    tail -n +1 -f your_log_file | xargs | myscript.sh

    【讨论】: