Предположим, вы попробовали что-то вроде этого:
$ 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[@]}"
}
EDIT: Г-н Шазелас прав. Я исправил свое решение, так что теперь вы можете использовать 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