将管道输出导入另一个脚本

10

我正在尝试将tail命令的输出导入到另一个bash脚本中进行处理:

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

然而,当我运行它时,myscript.sh内的$1参数从未被调用。我缺少什么?如何将输出转换为脚本的输入参数?PS-我想让tail永远运行,并继续将每个单独的行传递到脚本中。编辑:目前,myscripts.sh的整个内容是:
echo $1;

你缺少一个要分配给 $1 的参数。管道将 tail 的输出连接到脚本的标准输入。你能发布 myscript.sh,或者至少提供足够的信息来确定你是否需要一个参数(以及该参数应该是什么),以及它如何处理其标准输入中呈现的数据吗? - chepner
3个回答

19

通常,处理脚本标准输入的一种方法如下:

#!/bin/bash

while read line; do
    echo $line
done

这是一个非常粗糙的bash等价于cat的命令。它确实展示了一个关键事实:脚本内的每个命令都从shell继承其标准输入,因此您不需要特别做任何事情来访问输入数据。read从shell获取其输入,而在您的情况下,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是从哪里来的/被填充的? - slthomason
'foo' 只是命令行上的任意字符串。如果有一个字符串跟随您的命令,那么它将被分配给 $1。如果有第二个字符串,则会分配给 $2,以此类推。在您的原始示例中,没有在 myscript.sh 后面提供参数,这就是为什么 $1 没有值的原因。 - chepner
好的,那如何将tail命令的输出传递给myscript.sh呢?我是不是只需要将它整合到myscript.sh中?如果是这样,应该怎么做呢? - slthomason
抱歉我有点迟钝。当我正确插入时,它完美地工作了! - slthomason
1
@chepner,对于一个等效于cat的命令,循环应该使用echo "$line"而不是echo -n "$line" - Henk Langeveld
显示剩余2条评论

1

也许你把 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 中。


1
Piping连接一个进程的输出(stdout)到另一个进程的输入(stdin)。当进程启动时,stdin并不等同于发送给进程的参数。
你需要做的是将第一个进程输出的行转换为第二个进程的参数。这正是xargs命令的作用。
你所需要做的就是在初始命令和第二个进程之间加入一个xargs即可: tail -n +1 -f your_log_file | xargs | myscript.sh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接