Saya tidak yakin ini lebih baik daripada melakukannya di memori, tetapi dengan sedyang rkeluar infile untuk setiap baris di infile dan yang lain di sisi lain dari pipa bergantian Hruang lama dengan jalur 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'
KELUARAN
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
Saya melakukan ini dengan cara lain. Itu menyimpan beberapa dalam memori - menyimpan string seperti:
"$1" -
... untuk setiap baris dalam 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"
}
Ini sangat cepat. Ini catfile sebanyak yang ada baris dalam file ke file |pipe. Di sisi lain pipa input yang digabungkan dengan file itu sendiri sebanyak ada garis dalam file.
The casehal ini hanya untuk portabilitas - yashdan zshkedua add satu elemen untuk perpecahan, sementara mkshdan poshkedua satu kalah. ksh, dash, busybox, Dan bashsemua perpecahan untuk persis seperti berbagai bidang karena ada nol seperti yang dicetak oleh printf. Seperti yang ditulis di atas memberikan hasil yang sama untuk setiap shell yang disebutkan di atas pada mesin saya.
Jika file tersebut sangat panjang, mungkin ada $ARGMAXmasalah dengan terlalu banyak argumen yang perlu Anda perkenalkan xargsatau serupa.
Diberikan input yang sama yang saya gunakan sebelum output identik. Tapi, jika saya menjadi lebih besar ...
seq 10 10 10000 | nl -s, >/tmp/tmp
Itu menghasilkan file yang hampir identik dengan apa yang saya gunakan sebelumnya (tanpa 'Baris') - tetapi pada 1000 baris. Anda dapat melihat sendiri seberapa cepat:
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
Pada 1000 baris ada beberapa variasi kecil dalam kinerja antara shell - bashselalu yang paling lambat - tetapi karena satu-satunya pekerjaan yang mereka lakukan adalah menghasilkan string arg (1000 salinan filename -) efeknya minimal. Perbedaan kinerja antara zsh- seperti di atas - dan bash100 detik di sini.
Ini versi lain yang bisa digunakan untuk file dengan panjang berapa pun:
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"
)
Ini membuat soft-link ke arg pertama /tmpdengan nama semi-acak sehingga tidak akan terpaku pada nama file yang aneh. Itu penting karena catargumen diberikan ke pipa melalui xargs. catOutput disimpan <&3sementara sed pmeretas setiap baris dalam argumen pertama sebanyak ada baris dalam file itu - dan skripnya juga dimasukkan ke dalamnya melalui pipa. Sekali lagi pastemenggabungkan inputnya, tetapi kali ini hanya diperlukan dua argumen -lagi untuk input standar dan nama tautannya /dev/fd/3.
Yang terakhir - /dev/fd/[num]tautan - harus bekerja pada sistem linux dan banyak lagi selain itu, tetapi jika itu tidak membuat pipa bernama dengan mkfifodan menggunakan itu malah harus bekerja juga.
Hal terakhir yang dilakukannya adalah rmtautan lunak yang dibuatnya sebelum keluar.
Versi ini sebenarnya masih lebih cepat di sistem saya. Saya kira itu karena meskipun ia mengeksekusi lebih banyak aplikasi, ia mulai menyerahkan argumen mereka segera - padahal sebelum menumpuk semuanya terlebih dahulu.
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