Ich bin mir nicht sicher, ob dies besser ist, als es im Speicher zu tun, aber mit einem sed
, r
das seine Infile für jede Zeile in seiner Infile ausliest, und einem anderen auf der anderen Seite einer Pipe, die H
alte Leerzeichen mit Eingabezeilen abwechselt ...
cat <<\IN >/tmp/tmp
Row1,10
Row2,20
Row3,30
Row4,40
IN
</tmp/tmp sed -e 'i\
' -e 'r /tmp/tmp' |
sed -n '/./!n;h;N;/\n$/D;G;s/\n/ /;P;D'
AUSGABE
Row1,10 Row1,10
Row1,10 Row2,20
Row1,10 Row3,30
Row1,10 Row4,40
Row2,20 Row1,10
Row2,20 Row2,20
Row2,20 Row3,30
Row2,20 Row4,40
Row3,30 Row1,10
Row3,30 Row2,20
Row3,30 Row3,30
Row3,30 Row4,40
Row4,40 Row1,10
Row4,40 Row2,20
Row4,40 Row3,30
Row4,40 Row4,40
Ich habe das anders gemacht. Es speichert einige im Speicher - es speichert eine Zeichenfolge wie:
"$1" -
... für jede Zeile in der Datei.
pairs(){ [ -e "$1" ] || return
set -- "$1" "$(IFS=0 n=
case "${0%sh*}" in (ya|*s) n=-1;; (mk|po) n=+1;;esac
printf '"$1" - %s' $(printf "%.$(($(wc -l <"$1")$n))d" 0))"
eval "cat -- $2 </dev/null | paste -d ' \n' -- $2"
}
Es ist sehr schnell. Es ist cat
die Datei so oft wie es Zeilen in der Datei zu a gibt |pipe
. Auf der anderen Seite der Pipe wird diese Eingabe so oft mit der Datei selbst zusammengeführt, wie sich Zeilen in der Datei befinden.
Das case
Zeug ist nur für die Portabilität - yash
und zsh
beide fügen ein Element zum Split hinzu, während mksh
und posh
beide eines verlieren. ksh
, dash
, busybox
, Und bash
alle Split, um genau so viele Felder wie es Nullen sind als gedruckte durchprintf
. Wie oben beschrieben, werden auf meinem Computer für alle oben genannten Shells die gleichen Ergebnisse erzielt.
Wenn die Datei sehr lang ist, kann es zu $ARGMAX
Problemen mit zu vielen Argumenten kommen, die Sie in diesem Fall einführen müsstenxargs
oder Ähnliches.
Bei der gleichen Eingabe, die ich vor der Ausgabe verwendet habe, ist sie identisch. Aber wenn ich größer würde ...
seq 10 10 10000 | nl -s, >/tmp/tmp
Das erzeugt eine Datei, die fast mit der zuvor verwendeten identisch ist (ohne Zeile) - aber mit 1000 Zeilen. Sie können selbst sehen, wie schnell es ist:
time pairs /tmp/tmp |wc -l
1000000
pairs /tmp/tmp 0.20s user 0.07s system 110% cpu 0.239 total
wc -l 0.05s user 0.03s system 32% cpu 0.238 total
Bei 1000 Zeilen gibt es einige geringfügige Leistungsunterschiede zwischen den Shells - dies bash
ist ausnahmslos die langsamste -, aber da sie sowieso nur die Arg-Zeichenfolge (1000 Kopien filename -
) generieren, ist der Effekt minimal. Der Leistungsunterschied zwischen zsh
- wie oben - undbash
beträgt hier 100stel Sekunden.
Hier ist eine andere Version, die für eine Datei beliebiger Länge funktionieren sollte:
pairs2()( [ -e "$1" ] || exit
rpt() until [ "$((n+=1))" -gt "$1" ]
do printf %s\\n "$2"
done
[ -n "${1##*/*}" ] || cd -P -- "${1%/*}" || exit
: & set -- "$1" "/tmp/pairs$!.ln" "$(wc -l <"$1")"
ln -s "$PWD/${1##*/}" "$2" || exit
n=0 rpt "$3" "$2" | xargs cat | { exec 3<&0
n=0 rpt "$3" p | sed -nf - "$2" | paste - /dev/fd/3
}; rm "$2"
)
Es erstellt einen Softlink zu seinem ersten Argument /tmp
mit einem halb-zufälligen Namen, damit es nicht an seltsamen Dateinamen hängen bleibt. Das ist wichtig, weil cat
die Argumente über eine Leitung zugeführt werden xargs
. cat
‚s Ausgabe wird gespeichert , <&3
während sed
p
Rints jede Zeile in dem ersten arg so oft wie es Zeilen in dieser Datei ist - und sein Skript wird auch über ein Rohr , um es zugeführt. Wieder paste
verschmilzt seine Eingabe, aber dieses Mal ist es dauert nur zwei Argumente -
noch einmal für seine Standard - Eingabe und der Linknamen /dev/fd/3
.
Das Letzte - der /dev/fd/[num]
Link - sollte auf jedem Linux-System und vielen anderen funktionieren, aber wenn es keine Named Pipe erstellt mkfifo
und stattdessen verwendet, sollte es auch funktionieren.
Als letztes wird rm
der Softlink erstellt, der vor dem Beenden erstellt wird.
Diese Version ist eigentlich noch schneller auf meinem System. Ich vermute, es liegt daran, dass es, obwohl es mehr Anwendungen ausführt, beginnt, ihnen ihre Argumente sofort zu übergeben - wohingegen, bevor es sie alle zuerst stapelte.
time pairs2 /tmp/tmp | wc -l
1000000
pairs2 /tmp/tmp 0.30s user 0.09s system 178% cpu 0.218 total
wc -l 0.03s user 0.02s system 26% cpu 0.218 total