Home > Back-end >  GNU shell doing multiple things in a nested diff all at once
GNU shell doing multiple things in a nested diff all at once

Time:03-04

I am trying to do a few things in a single line and this is my attempt:

coolc -P p good.cool | xargs -I {} sh -c "diff <(sed 's/@[0-9] /@/g' {}) <(sed 's/@[0-9] /@/g' good.out)"
  1. I have a file called good.out and I want to run sed on it: sed 's/@[0-9] /@/g' good.out
  2. I want to run coolc -P p good.cool which prints result to stdout
  3. I want to use the output from (2) in sed 's/@[0-9] /@/g' {}
  4. I want to diff (1) and (3)

Is it possible doing all of these without creating a new files and all in a single line?

CodePudding user response:

Assuming that the original code was wrong to use xargs, and you really want to run diff only once:

diff <(coolc -P p good.cool | sed 's/@[0-9] /@/g') \
     <(sed 's/@[0-9] /@/g' good.out)

CodePudding user response:

There are certainly optimizations that could be done to this (running sed on the same good.out file over and over is not very efficient), but the shortest possible translation of your code to something that works (written assuming that there was ever actually a good reason to use xargs):

#!/usr/bin/env bash
while IFS= read -r filename; do
  diff <(sed 's/@[0-9] /@/g' "$filename") \
       <(sed 's/@[0-9] /@/g' good.out)
done < <(coolc -P p good.cool)
  • bash, not sh, needs to be used for process substitution syntax to be available.
  • Insofar as the purpose of coolc -P p good.cool | xargs ... is to run ... once per item written into the stdout of coolc -P p good.cool, this is better replaced with a BashFAQ #1 while read loop.
  • BashFAQ #24: I set variables in a loop that's in a pipeline. Why do they disappear after the loop terminates? Or, why can't I pipe data to read? -- this explains why the use of <( ) to feed the while read loop instead of a pipe.
  • Related