[root@server]# awk '!seen[$0]++' out.txt > cleaned
awk: (FILENAME=out.txt FNR=8547098) fatal error: internal error
Aborted
[root@server]#
"" Server "" memiliki: 8 GByte RAM + 16 GByte SWAP, x> 300 GByte ruang kosong, amd64, desktop CPU. Linux Ilmiah 6.6. Tidak ada lagi yang dijalankan untuk membuat LOAD. Awk batal setelah beberapa detik .. out.txt adalah ~ 1,6 GByte. GNU Awk 3.1.7.
Pertanyaan : Bagaimana saya bisa menghapus garis duplikat sambil menjaga urutan garis? Kasus juga penting, misalnya: "A" dan "a" adalah dua baris yang berbeda, harus tetap dipertahankan. Tapi "a" dan "a" adalah duplikat, hanya yang pertama diperlukan.
Jawaban bisa dalam apa saja .. jika awk tidak baik untuk ini .. maka perl / sed .. apa masalahnya?
[root@server]# ulimit -a
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 0
file size (blocks, -f) unlimited
pending signals (-i) 61945
max locked memory (kbytes, -l) 99999999
max memory size (kbytes, -m) unlimited
open files (-n) 999999
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
real-time priority (-r) 0
stack size (kbytes, -s) 99999999
cpu time (seconds, -t) unlimited
max user processes (-u) 61945
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited
[root@server]#
Pembaruan: Saya mencoba ini pada mesin RHEL, tidak dibatalkan, tetapi saya tidak punya waktu untuk menunggu sampai selesai .. mengapa SL linux berbeda dari RHEL?
Pembaruan: Saya mencoba pada Ubuntu 14 virtual gues .. sejauh ini berhasil! Ini bukan masalah ulimit: mawk 1.3.3
root@asdf-VirtualBox:~# ulimit -a
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 0
file size (blocks, -f) unlimited
pending signals (-i) 51331
max locked memory (kbytes, -l) 64
max memory size (kbytes, -m) unlimited
open files (-n) 1024
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
real-time priority (-r) 0
stack size (kbytes, -s) 8192
cpu time (seconds, -t) unlimited
max user processes (-u) 51331
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited
root@asdf-VirtualBox:~#
sumber
awk
versi dalam dua mesin?out.txt
? Apakah perintah yang sama berfungsi jika Anda mencobanya pada file yang lebih kecil? Berapa banyak pengguna di mesin? Apakah ada cukup memori yang tersedia untuk proses ini? Apakah ada yang spesial tentang baris 8547098 dari file input?Jawaban:
Saya ragu itu akan membuat perbedaan tetapi, untuk berjaga-jaga, inilah cara melakukan hal yang sama di Perl:
Jika masalahnya adalah menjaga garis-garis unik dalam memori, itu akan memiliki masalah yang sama dengan yang
awk
Anda coba. Jadi, pendekatan lain dapat:Bagaimana itu bekerja:
Pada sistem GNU,
cat -n
akan menambahkan nomor baris ke setiap baris mengikuti sejumlah spasi dan diikuti oleh karakter <tab> .cat
mem-pipe representasi input ini kesort
.sort
's-k2
pilihan menginstruksikan hanya mempertimbangkan karakter dari kolom kedua sampai akhir baris ketika menyortir, dansort
perpecahan bidang secara default pada white-space (ataucat
' s dimasukkan ruang dan <tab> ) .Ketika diikuti oleh
-k1n
,sort
pertimbangkan bidang ke-2 terlebih dahulu, dan kemudian yang kedua — dalam kasus-k2
bidang yang identik — bidang itu menganggap bidang ke-1 tetapi sebagai diurutkan secara numerik. Jadi garis yang diulang akan diurutkan bersama tetapi dalam urutan yang muncul.uniq
— yang diperintahkan untuk mengabaikan bidang pertama (-f1
- dan juga dipisahkan oleh spasi) —dan yang menghasilkan daftar baris unik di file asli dan disalurkan kembali kesort
.sort
mengurutkan pada bidang pertama (cat
nomor baris yang disisipkan) secara numerik, mendapatkan urutan kembali ke apa yang ada di file asli dan pipa hasil ini kecut
.cut
menghapus nomor baris yang dimasukkan olehcat
. Ini dipengaruhi olehcut
pencetakan hanya dari bidang ke-2 hingga akhir baris (dancut
pembatas default adalah karakter <tab> ) .Menggambarkan:
sumber
sort
! Tetapi sebagian besarsort
dapat melakukannyauniq
sendiri sehingga Anda dapat mempersingkat skrip Anda dengansort -uk2 | sort -bk1,1n
sort
? Saya pikir-u
itu fitur GNU.-u
dan menentukan bahwa itu harus mengabaikan bidang 1? Menurutman sort
,-u
ini bukan salah satu opsi yang mungkin untuk-f
, jadi saya tidak berpikir itu bisa digunakan di sini.EDIT 1: Apakah ini benar-benar berfungsi? (perbandingan)
Case1 : 100_000_000 angka acak (5 digit masing-masing), 566Mbytes, 31_212 nilai yang berbeda:
Kasus 2 : 50_000_000 angka rand (masing-masing 10 digit), 516Mbytes, 48_351_464 nilai yang berbeda:
(angka-angka berikut ini tidak terlalu tepat):
sol2 dengan cache adalah:
Sortir juga dapat dioptimalkan dengan menambahkan opsi cache (tidak dilakukan).
Satu kesimpulan cepat:
sort
adalah perintah yang fantastis!sumber
sort -uk2
dansort -nk1,1
berbeda. Yang pertama mempertimbangkan dari kunci 2cd ke akhir baris, yang kedua hanya mempertimbangkan kunci pertama. Anda harus mengubahnya disort -nk1
sana - bahkan mungkin lebih cepat, tetapi pasti akan lebih andal. By the way - itu adalah beberapa kotak cantik.cat -n
juga tab ? Saya tidak tahu bagaimana perintah itu bekerja.cat -n
masing-masingline
dalamspaces + the number + \t + line
- format ideal untuk sortir dan memotongSaya sudah menggunakan
BINMODE = rw: untuk menjaga terminator garis akhir tetap bahagia. (Saya tinggal di lingkungan os campuran)
Logikanya sederhana.
Jika baris saat ini tidak dalam array asosiatif kemudian tambahkan ke array asosiatif dan cetak ke output.
Mungkin ada keterbatasan memori dengan pendekatan ini. Untuk file yang sangat besar dan kumpulan file, saya telah menggunakan variasi ini, menggunakan penyimpanan file untuk melewati batasan.
sumber
Semantik yang mempertahankan pesanan dari masalah Anda memiliki properti yang luar biasa: Anda dapat membagi masalah tersebut. Anda dapat melakukannya
split -l 1000000
pada file input; potongan-potongan 1000000-line yang dihasilkannya memiliki nama yang dipesan secara leksikal yang bagus; kemudian uniqify bagian; dan kemudian (sebagai pass kedua) menyatukan output dari mereka.Ini menyelesaikan masalah kehabisan memori (dengan membatasi kebutuhan memori) dengan mengorbankan mengubahnya menjadi solusi multipas.
Secara khusus:
Hasilkan data input:
Pisahkan data input:
Jalankan uniqifier sekaligus (mempertahankan semua jalur input unik dalam memori):
Jalankan uniqifier pada bagian-bagian yang terpisah (hanya mempertahankan jalur input unik dari masing-masing bagian dalam memori), lalu kurangi sebagai lintasan kedua:
Membandingkan:
Saya tidak tahu rasio garis unik dan non-unik dalam input Anda, atau seberapa baik garis input tercampur - jadi ada beberapa penyesuaian yang harus dilakukan dalam hal jumlah file split yang Anda butuhkan.
sumber
Pendekatan lain (layak posting sebagai jawaban terpisah) adalah: alih-alih pendekatan split-file yang membuat file temp, lakukan batching dalam perangkat lunak uniqifier itu sendiri. Misalnya, menggunakan implementasi uniqifier Ruby untuk tujuan penjelasan:
Idenya adalah untuk menghapus hash-set sesekali. Maka ini menjadi berulang:
Jadi, Anda dapat menjalankan versi yang dibatasi ini berulang kali, hingga jumlah baris tidak berubah dari satu iterasi ke yang berikutnya.
Perhatikan bahwa teknik capped-uniqm ini tidak tergantung pada bahasa: Anda dapat menghapus
lines_seen
larik setiap baris N apakah Anda menggunakan awk, python, perl, C ++, dll. Ada metode set-clear untuk semua bahasa ini; Saya percayaawk
'sdelete
adalah non-standar tapi umum.sumber