如何通过 shell 脚本将标题行注入管道?

如何通过 shell 脚本将标题行注入管道?

我正在研究一个通过管道将数据从一台服务器发送到另一台服务器进行处理的过程。

虽然这不是确切的命令,但它可能看起来像这样:

tail -f logfile | grep "abc" | grep "def" | grep -v "ghi" | netcat -q 0 n.n.n.n 7777

我想将所有这些 grep 包装到一个脚本中,更重要的是在管道前面加上netcat一个标识符,因此命令如下所示:

tail -f logfile | myscript.sh {id}

另一端监听的脚本应该收到:

{id}
[Line 1 of the logfile]
[Line 2 of the logfile]
...

将其包装在脚本中很容易:

#!/bin/sh
id=$1
grep "abc" | grep "def" | grep -v "ghi" | netcat -q 0 n.n.n.n 7777

但我不知道如何$id在一开始就注射。

接收端正在使用

 socat -u tcp-l:7777,fork system:/dev/receivePipe

所以如果我可以通过其他方式获取 id(例如以某种方式作为参数/dev/receivePipe),或者通过环境变量,那么这样也可以。

编辑:最终答案是在已接受答案的评论中得出的:

#!/bin/sh
{
  printf '%s\n' $1
  grep "abc" | grep "def" | grep -v "ghi" 
} | netcat -q 0 192.168.56.105 7777

答案1

做就是了:

#! /bin/sh -
{
  printf '%s\n' "${1-default-id}"
  awk '/abc/ && /def/ && ! /ghi/'
} | socat - tcp:n.n.n.n:7777

${1-default-id}如果指定或以其他方式扩展为第一个位置参数default-id。替换为${1?}如果未传递任何参数则退出并返回错误(或者${1?The error message}指定错误消息而不是默认消息)。

我们将运行printf以输出 ID 和过滤命令的命令组的输出重定向到/ 。grepawksocatnetcat

或者仅在一行已被读取且匹配时打印 ID:

#! /bin/sh -
ID=${1-default-id} awk '
  /abc/ && /def/ && ! /ghi/ {
    if (!already_printed++) print ENVIRON["ID"]
    print
  }' | socat - tcp:n.n.n.n:7777

或者在每一行前面添加 ID(和空格字符):

#! /bin/sh -
ID=${1-default-id} awk '
  /abc/ && /def/ && ! /ghi/ {
    print ENVIRON["ID"], $0
  }' | socat - tcp:n.n.n.n:7777

请注意,当输入到管道(除 tty 设备以外的任何设备)时,awklike会缓冲它们的输出。使用(aka )grep的 GNU 实现,您可以在每个之后添加一个调用来强制刷新该缓冲区。另请参见的。在大多数实现中,执行 a也会强制刷新。 GNU 实现有一个选项可以在每行输出后强制刷新。awkgawkfflush()print-Winteractivemawkawksystem("")grep--line-buffered

另请注意,它tail -f logfile是 的缩写tail -n 10 -f logfile。您实际上可能希望tail -n +1 -f logfile处理整个日志文件,然后tail继续f处理该文件,或者tail -n 0 -f logfile仅处理正在添加的行今后

相关内容