组合多进程替换

mus*_*hil 6 command-line bash process-substitution

假设你尝试过这样的事情:

$ paste ../data/file-{A,B,C}.dat
Run Code Online (Sandbox Code Playgroud)

并意识到您想在粘贴之前对每个文件进行排序(假设是数字)。然后,使用进程替换,您需要编写如下内容:

$ paste <(sort -n ../data/file-A.dat) \
        <(sort -n ../data/file-B.dat) \
        <(sort -n ../data/file-C.dat)
Run Code Online (Sandbox Code Playgroud)

在这里你会看到很多重复,这不是一件好事。因为每个进程替换都是相互隔离的,所以不能使用任何跨越多个进程替换的大括号扩展或路径名扩展(通配符)。

是否有一种工具可以让您以紧凑的方式(例如通过给予sort -n../data/file-{A,B,C}.dat单独)编写并为您编写整个命令行?

Sté*_*las 2

你可以这样做:

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

或者将其自动化为函数

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
Run Code Online (Sandbox Code Playgroud)

(在某些ksh实现中,您需要替换localtypeset

要适应任何任意命令(并证明eval正确使用时是安全的),您可以这样做:

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
Run Code Online (Sandbox Code Playgroud)