在处理管道时与awk交互

时间:2018-06-15 13:16:24

标签: bash shell awk

通过管道处理awk时,有一种方法可以使/dev/stdin互动。

想象一下,我有一个不断生成数据的程序。示例:

$ od -vAn -tu2 -w2 < /dev/urandom
 2357
60431
19223
...    

此数据由非常高级的awk脚本通过管道进行处理:

$ od -vAn -tu2 -w2 < /dev/urandom | awk '{print}'

问题:是否可以使此awk计划互动,以便:

  • 程序不断打印输出
  • 当按下一个键时(例如z),它开始仅为从管道读取的每一行输出0
  • 再次按下该键时,它会继续输出原始数据,显然会跳过已打印为0的已处理记录。

问题:

  • /dev/stdin(也称为-)已在使用中,因此需要使用/dev/tty来获取键盘交互,还是有另一种方式?

  • getline key < "/dev/tty"等待,直到遇到RS为止,因此在默认情况下,您需要按两个键( z Enter ):

    $ awk 'BEGIN{ getline key < "/dev/tty"; print key}'
    

    这是可以接受的,但我更喜欢单按键。

    那么,是否可以在本地设置RS以使getline读取单个字符?这样我们就可以在RS之后在本地修改getline并重置它。另一种方法可能是使用shell函数read。但它在bashzsh之间不兼容。

  • getline等待输入直到时间结束。所以它基本上停止了管道的处理。有gawk extention允许您设置超时,但这仅在gawk 4.2之后可用。 所以我相信这可能有用:

    awk '{print p ? 0 : $0 }
         { PROCINFO["/dev/tty", "READ_TIMEOUT"]=1;
           while (getline key < "/dev/tty") p=key=="z"?!p:p
         }
    

    但是,我无法访问gawk 4.2 (更新:这不起作用)

请求:

  1. 我更喜欢完整的POSIX兼容版本,它是或完全是awk或使用POSIX兼容的系统调用
  2. 如果无法做到这一点,可以使用3.1.7之前的gawk扩展和shell独立系统调用。
  3. 作为最后的手段,我会接受任何shell-awk结构,这样可以在awk连续读取数据的单一条件下实现这一点(所以我在这里想多个管道)

1 个答案:

答案 0 :(得分:1)

经过一些搜索,我想出了一个Bash脚本,可以执行此操作。这个想法是将唯一可识别字符串注入awk正在处理的管道中。原始程序od和bash脚本都写入管道。为了不破坏这些数据,我使用stdbuf运行行缓冲的程序od。此外,由于是处理按键的bash脚本,因此原始程序和awk脚本都必须在后台运行。因此,需要采取干净的退出策略。按下键q时,awk将退出,而终止awk时,od将自动终止。

最后,它看起来像这样:

#!/usr/bin/env bash

# make a fifo which we use to inject the output of data-stream
# and the key press
mkfifo foo

# start the program in line-buffer mode, writing to FIFO
# and run it in the background
stdbuf -o L  od -vAn -tu2 -w2 < /dev/urandom > foo &

# run the awk program that processes the identified key-press
# also run it in the background and insert a clear EXIT strategy
awk '/key/{if ($2=="q") exit; else p=!p}
     !p{print}
      p{print 0}' foo &

# handle the key pressing
# if a key is pressed inject the string "key <key>" into the FIFO
# use "q" to exit
while true; do
    read -rsn1 key
    echo "key $key" > foo 
    [[ $key == "q" ]] && exit
done

注意:我忽略了密钥必须为z

的概念。

一些有用的帖子: