假设你尝试过这样的事情:
$ 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
实现中,您需要替换local
为typeset
)
要适应任何任意命令(并证明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