結合多進程替換

結合多進程替換

假設你嘗試過這樣的事情:

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

並意識到您想要在貼上之前對每個文件進行排序(假設是數字排序)。然後,使用進程替換,您需要編寫以下內容:

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

在這裡你會看到很多重複,這不是一件好事。由於每個進程替換都是相互隔離的,因此您不能使用跨越多個進程替換的任何大括號擴展或路徑名擴展(通配符)。

是否有一個工具可以讓您以緊湊的方式編寫此內容(例如,通過分別給出sort -n../data/file-{A,B,C}.dat)並為您編寫整個命令行?

答案1

你可以這樣做:

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

或將其自動化為函數

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

(在某些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

答案2

請參見這裡, 為什麼eval使用起來會很危險。正如你會注意到的,這是一個非常強大的工具,但同時可以造成很大的損害

以下腳本將安全地執行您想要的操作。

sort_ps () 
{ 
    local cmd="$1" p=()
    shift;
    for f in "$@"; do
        p+=(<(sort -n "$f"));
    done
    "$cmd" "${p[@]}"
}

編輯:查澤拉斯先生是對的。我修復了我的解決方案,因此您現在可以使用sort_ps paste file1.txt file2.txt file2.txt ... fileN.txt它。感謝史蒂芬審閱我的答案。

範例輸出:

rany$ sort_ps sprunge foo1.txt foo.txt 
http://sprunge.us/EBZf?/dev/fd/62
http://sprunge.us/TQGC?/dev/fd/62

相關內容