Combining multiple process substitution

musiphil

Suppose you tried something like this:

$ paste ../data/file-{A,B,C}.dat

and realize that you want to sort each file (numerically, let's suppose) before pasting. Then, using process substitution, you need to write something like this:

$ paste <(sort -n ../data/file-A.dat) \
        <(sort -n ../data/file-B.dat) \
        <(sort -n ../data/file-C.dat)

Here you see a lot of duplication, which is not a good thing. Because each process substitution is isolated from one another, you cannot use any brace expansion or pathname expansion (wildcards) that spans multiple process substitution.

Is there a tool that allows you to write this in a compact way (e.g. by giving sort -n and ../data/file-{A,B,C}.dat separately) and composes the entire command line for you?

Stéphane Chazelas

You could do:

eval paste '<(sort -n ../data/file-'{A,B,C}'.dat)'

Or to automate it as a function

sort_paste() {
  local n i cmd
  n=1 cmd=paste
  for i do
    cmd="$cmd <(sort -n -- \"\${$n}\")"
    n=$(($n + 1))
  done
  eval "$cmd"
}
sort_paste  ../data/file-{A,B,C}.dat

(in some ksh implementations, you need to replace local with typeset)

To adapt to any arbitrary command, (and to prove that eval can be safe when used properly), you could do:

xproc() {
  local n i cmd stage stage1 stage2 stage3
  cmd= xcmd= stage=1 n=1
  stage1='cmd="$cmd \"\${$n}\""'
  stage2='xcmd="$xcmd \"\${$n}\""'
  stage3='cmd="$cmd <($xcmd \"\${$n}\")"'
  for i do
    if [ -z "$i" ] && [ "$stage" -le 3 ]; then
      stage=$(($stage + 1))
    else
      eval 'eval "$stage'"$stage\""
    fi
    n=$(($n + 1))
  done
  eval "$cmd"
}

xproc paste '' sort -n -- '' ../data/file-{A,B,C}/dat

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related