No estoy seguro de que esto sea mejor que hacerlo en la memoria, pero con un sedque rborra su archivo para cada línea en su archivo y otro en el otro lado de una tubería que alterna el Hespacio antiguo con líneas de entrada ...
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'
SALIDA
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
Hice esto de otra manera. Almacena algunos en la memoria, almacena una cadena como:
"$1" -
... para cada línea en el archivo.
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 muy rápido. Es catel archivo tantas veces como haya líneas en el archivo a |pipe. En el otro lado de la tubería, esa entrada se fusiona con el archivo en sí tantas veces como haya líneas en el archivo.
El casematerial es sólo para la portabilidad - yashy zshtanto un elemento añadir a la división, mientras mkshy poshtanto uno perder. ksh, dash, busybox, Y bashtoda división a cabo exactamente como muchos campos, ya que hay ceros como impreso por printf. Como está escrito, lo anterior genera los mismos resultados para cada uno de los shells mencionados anteriormente en mi máquina.
Si el archivo es muy largo, puede haber $ARGMAXproblemas con demasiados argumentos, en cuyo caso necesitaría introducir xargso similar también.
Dada la misma entrada que usé antes de que la salida sea idéntica. Pero, si fuera más grande ...
seq 10 10 10000 | nl -s, >/tmp/tmp
Eso genera un archivo casi idéntico al que usé antes (sin 'Fila') , pero con 1000 líneas. Puedes ver por ti mismo lo rápido que es:
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 líneas hay una ligera variación en el rendimiento entre los shells, bashes invariablemente el más lento, pero debido a que el único trabajo que hacen de todos modos es generar la cadena arg (1000 copias de filename -) el efecto es mínimo. La diferencia en el rendimiento entre zsh- como arriba - y bashes la centésima de segundo aquí.
Aquí hay otra versión que debería funcionar para un archivo de cualquier longitud:
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 enlace suave a su primer argumento /tmpcon un nombre semi-aleatorio para que no se obsesione con nombres de archivos extraños. Eso es importante porque catlos args se alimentan a través de una tubería xargs. catLa salida de se guarda en <&3mientras sed pborra cada línea en el primer argumento tantas veces como haya líneas en ese archivo, y su script también se alimenta a través de una tubería. Nuevamente pastefusiona su entrada, pero esta vez solo toma dos argumentos -nuevamente para su entrada estándar y el nombre del enlace /dev/fd/3.
Ese último, el /dev/fd/[num]enlace, debería funcionar en cualquier sistema Linux y muchos más, pero si no crea una tubería con nombre mkfifoy usarlo, también debería funcionar.
Lo último que hace es rmel enlace suave que crea antes de salir.
Esta versión es realmente más rápida aún en mi sistema. Supongo que es porque aunque ejecuta más aplicaciones, comienza a entregarles sus argumentos de inmediato, mientras que antes los apilaba primero.
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