Saya tidak yakin ini lebih baik daripada melakukannya di memori, tetapi dengan sed
yang r
keluar infile untuk setiap baris di infile dan yang lain di sisi lain dari pipa bergantian H
ruang 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 cat
file 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 case
hal ini hanya untuk portabilitas - yash
dan zsh
kedua add satu elemen untuk perpecahan, sementara mksh
dan posh
kedua satu kalah. ksh
, dash
, busybox
, Dan bash
semua 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 $ARGMAX
masalah dengan terlalu banyak argumen yang perlu Anda perkenalkan xargs
atau 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 - bash
selalu 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 bash
100 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 /tmp
dengan nama semi-acak sehingga tidak akan terpaku pada nama file yang aneh. Itu penting karena cat
argumen diberikan ke pipa melalui xargs
. cat
Output disimpan <&3
sementara sed
p
meretas setiap baris dalam argumen pertama sebanyak ada baris dalam file itu - dan skripnya juga dimasukkan ke dalamnya melalui pipa. Sekali lagi paste
menggabungkan 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 mkfifo
dan menggunakan itu malah harus bekerja juga.
Hal terakhir yang dilakukannya adalah rm
tautan 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