kvantour
kvantour

Reputation: 26481

Interacting with awk while processing a pipe

GIs there a way to make awk interactive when it is processing /dev/stdin via a pipe.

Imagine I have a program which continuously generates data. Example :

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

This data is being processed by a very advanced awk script by means of a pipe :

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

Question: Is it possible to make this awk program interactive such that :

Problems:

Requests:

  1. I would prefer a full POSIX compliant version, which is or entirely awk or using POSIX compliant system calls
  2. If this is not possible, gawk extensions prior to 3.1.7 can be used and shell independent system calls.
  3. As a last resort, I would accept any shell-awk construct which would make this possible under the single condition that the data is only read continuously by awk (so I'm thinking multiple pipes here).

Upvotes: 1

Views: 1459

Answers (1)

kvantour
kvantour

Reputation: 26481

After some searching, I came up with a Bash script that allows doing this. The idea is to inject a unique identifiable string into the pipe that awk is processing. Both the original program od and the bash script write to the pipe. In order not to mangle that data, I used stdbuf to run the program od line-buffered. Furthermore, since it is the bash-script that handles the key-press, both the original program and the awk script have to run in the background. Therefore a clean exit strategy needs to be in place. Awk will exit when the key q is pressed, while od will terminate automatically when awk is terminated.

In the end, it looks like this :

#!/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

note: I ignored the concept that the key has to be z

Some useful posts :

Upvotes: 1

Related Questions