Supongamos que intentaste algo como esto:
$ paste ../data/file-{A,B,C}.dat
y te das cuenta de que quieres ordenar cada archivo (numéricamente, supongamos) antes de pegarlo. Luego, usando la sustitución de procesos, debes escribir algo como esto:
$ paste <(sort -n ../data/file-A.dat) \
<(sort -n ../data/file-B.dat) \
<(sort -n ../data/file-C.dat)
Aquí se ve mucha duplicación, lo cual no es bueno. Debido a que cada sustitución de procesos está aislada entre sí, no puede utilizar ninguna expansión de llave o expansión de nombre de ruta (comodines) que abarque múltiples sustituciones de procesos.
¿Existe alguna herramienta que le permita escribir esto de forma compacta (por ejemplo, dando sort -n
y ../data/file-{A,B,C}.dat
por separado) y compone toda la línea de comando por usted?
Respuesta1
Podrías hacerlo:
eval paste '<(sort -n ../data/file-'{A,B,C}'.dat)'
O automatizarlo como una función.
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
(en algunas ksh
implementaciones, es necesario reemplazar local
con typeset
)
Para adaptarse a cualquier comando arbitrario (y demostrar que eval
puede ser seguro cuando se usa correctamente), puede hacer:
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
Respuesta2
Por favor miraaquí, por qué eval
puede ser peligroso de usar. Como notarás, es unherramienta muy poderosa, pero al mismo tiempo puedecausar mucho daño.
El siguiente script hará lo que usted quiera: de forma segura.
sort_ps ()
{
local cmd="$1" p=()
shift;
for f in "$@"; do
p+=(<(sort -n "$f"));
done
"$cmd" "${p[@]}"
}
EDITAR: El Sr. Chazelas tiene razón. Arreglé mi solución, por lo que ahora puedes usarla sort_ps paste file1.txt file2.txt file2.txt ... fileN.txt
en su lugar. Gracias Stéphane por revisar mi respuesta.
Salida de muestra:
rany$ sort_ps sprunge foo1.txt foo.txt
http://sprunge.us/EBZf?/dev/fd/62
http://sprunge.us/TQGC?/dev/fd/62