Angenommen, Sie hätten Folgendes versucht:
$ paste ../data/file-{A,B,C}.dat
und stellen Sie fest, dass Sie jede Datei (nehmen wir an, numerisch) vor dem Einfügen sortieren möchten. Dann müssen Sie mithilfe der Prozesssubstitution etwas wie das Folgende schreiben:
$ paste <(sort -n ../data/file-A.dat) \
<(sort -n ../data/file-B.dat) \
<(sort -n ../data/file-C.dat)
Hier sehen Sie viele Duplikate, was nicht gut ist. Da jede Prozessersetzung von den anderen isoliert ist, können Sie keine Klammern oder Pfadnamenerweiterungen (Platzhalter) verwenden, die mehrere Prozessersetzungen umfassen.
Gibt es ein Tool, mit dem Sie dies kompakt schreiben können (z. B. indem Sie sort -n
und ../data/file-{A,B,C}.dat
getrennt angeben) und das die gesamte Befehlszeile für Sie zusammenstellt?
Antwort1
Du könntest es tun:
eval paste '<(sort -n ../data/file-'{A,B,C}'.dat)'
Oder es als Funktion zu automatisieren
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
(in einigen ksh
Implementierungen müssen Sie local
durch ersetzen typeset
)
Zur Anpassung an beliebige Befehle (und um zu beweisen, dass sie eval
bei ordnungsgemäßer Verwendung sicher sein können) können Sie Folgendes tun:
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
Antwort2
Bitte beachten SieHier, warum eval
kann gefährlich sein, zu verwenden. Wie Sie feststellen werden, ist es einsehr leistungsstarkes Werkzeug, kann aber gleichzeitigviel Schaden anrichten.
Das folgende Skript erledigt das Gewünschte – und zwar sicher.
sort_ps ()
{
local cmd="$1" p=()
shift;
for f in "$@"; do
p+=(<(sort -n "$f"));
done
"$cmd" "${p[@]}"
}
EDIT: Herr Chazelas hat Recht. Ich habe meine Lösung korrigiert, sodass Sie jetzt sort_ps paste file1.txt file2.txt file2.txt ... fileN.txt
stattdessen verwenden können. Vielen Dank, Stephane, für die Überprüfung meiner Antwort.
Beispielausgabe:
rany$ sort_ps sprunge foo1.txt foo.txt
http://sprunge.us/EBZf?/dev/fd/62
http://sprunge.us/TQGC?/dev/fd/62