Droopycom
Droopycom

Reputation: 1931

zsh and/or bash redirections to compare the input and output of a process

I have a command that take data through stdin and produce output on stdout. I need a wrapper for that command that would only output the diff between the input and output. Preferably without using temp files or name pipes, and I need it to work with macOS shells.

I now I can diff the output of 2 commands with diff <(cmd1) <(cmd2) and I now I could split the input into 2 streams with tee, but I'm not sure if I can somehow connect those 2 things to achieve what I want.

Described as a diagram, I want this:

         /---> process --->\
stdin-->+                  diff ---> stdout
         \---------------->/

Upvotes: 1

Views: 43

Answers (2)

ghoti
ghoti

Reputation: 46876

I thought at first it might be fun to hand fo process in a coproc command, but that proved unnecessarily complex for the wrapper. Instead, I have this.

First, the script that modifies some lines (which I've called change):

#!/usr/bin/env bash

while read -r -s ; do
    case "$REPLY" in
        *[abc]*) printf '%s\n' "${REPLY^^}" ;;
        *) printf '%s\n' "${REPLY}" ;;
    esac
done

This script runs in a more current version of bash than ships with macos, but that doesn't matter, it's only an example.

And the wrapper (which I've called thing):

#!/bin/bash

text="$(cat)"

diff <he(echo "$text") <(change <<< "$text" )

And if you're looking for only the words that have chamged,yo might use the following to replace the diff line:

comm -13 <(echo "$text") <(change <<< "$text" )

This script is simple enough that is will run in zsh as well without chamges.

Upvotes: 0

Ed Morton
Ed Morton

Reputation: 204381

diff <(cmd1) <(cmd2) uses temp files and it sounds like you're OK with that so it's not clear why say you want to avoid temp files. I'd just keep it simple and use a temp file:

$ cat tst.sh
#!/usr/bin/env bash

tmpIn=$(mktemp) || exit 1
trap 'rm -f "$tmpIn"; exit' EXIT

tee "$tmpIn" |
sed 's/foo/bar/g' |
diff "$tmpIn" -

$ printf 'this\nfoo\nis\nfoo\nit\n' | ./tst.sh
2c2
< foo
---
> bar
4c4
< foo
---
> bar

The sed command is obviously a placeholder for whatever your process command is.

Upvotes: 2

Related Questions