Non sono sicuro che sia meglio che farlo in memoria, ma con una sed
che r
segna la sua infile per ogni linea nella sua infile e un'altra dall'altra parte di una pipe alternando il H
vecchio spazio con le linee di input ...
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'
PRODUZIONE
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
L'ho fatto in un altro modo. Memorizza alcuni in memoria - memorizza una stringa come:
"$1" -
... per ogni riga nel file.
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"
}
È molto veloce. È cat
il file tante volte quante sono le righe nel file a |pipe
. Dall'altro lato della pipa quell'input viene unito al file stesso tante volte quante sono le righe nel file.
La case
roba è solo per la portabilità - yash
e zsh
sia aggiunta un elemento di per la scissione, mentre mksh
e posh
entrambi perde una. ksh
, dash
, busybox
, E bash
tutto diviso fuori esattamente come molti campi come ci sono zeri come stampato da printf
. Come scritto sopra, si ottengono gli stessi risultati per ognuna delle shell sopra menzionate sulla mia macchina.
Se il file è molto lungo, potrebbero esserci $ARGMAX
problemi con troppi argomenti nel qual caso dovresti introdurre xargs
o simili.
Dato lo stesso input che ho usato prima che l'output fosse identico. Ma se dovessi diventare più grande ...
seq 10 10 10000 | nl -s, >/tmp/tmp
Ciò genera un file quasi identico a quello che ho usato prima (senza "Row") , ma a 1000 righe. Puoi vedere tu stesso quanto è veloce:
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
A 1000 linee c'è una leggera variazione nelle prestazioni tra le shell - bash
è invariabilmente la più lenta - ma poiché l'unico lavoro che fanno comunque è generare la stringa arg (1000 copie di filename -
) l'effetto è minimo. La differenza di prestazioni tra zsh
- come sopra - ed bash
è qui al centesimo di secondo.
Ecco un'altra versione che dovrebbe funzionare per un file di qualsiasi lunghezza:
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"
)
Crea un soft-link al suo primo argomento in /tmp
con un nome semi-casuale in modo che non si blocchi su nomi di file strani. Questo è importante perché cat
gli arg vengono alimentati tramite una pipe xargs
. cat
L'output viene salvato <&3
mentre viene sed
p
stampata ogni riga nel primo argomento tante volte quante sono le righe in quel file - e il suo script viene anche inviato ad esso tramite una pipe. paste
Unisce nuovamente il suo input, ma questa volta prende solo due argomenti -
ancora per il suo input standard e il nome del collegamento /dev/fd/3
.
Quest'ultimo - il /dev/fd/[num]
collegamento - dovrebbe funzionare su qualsiasi sistema Linux e molti altri ancora, ma se non crea una pipa denominata mkfifo
e ne utilizza invece dovrebbe funzionare anche.
L'ultima cosa che fa è rm
il soft link che crea prima di uscire.
Questa versione è in realtà ancora più veloce sul mio sistema. Immagino sia perché, sebbene esegua più applicazioni, inizia immediatamente a consegnare loro i loro argomenti, mentre prima li impilava tutti per primi.
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