Bagaimana cara membagi file besar menjadi dua bagian, pada suatu pola?
Diberikan contoh file.txt
:
ABC
EFG
XYZ
HIJ
KNL
Saya ingin membagi file ini XYZ
sedemikian rupa sehingga file1
berisi baris up-to XYZ
dan sisa baris di file2
.
text-processing
sed
awk
split
d.putto
sumber
sumber
XYZ
jalur dimasukkan dalam output atau tidak?Jawaban:
Dengan
awk
Anda dapat melakukan:Penjelasan:
awk
Argumen pertama (out=file1
) mendefinisikan variabel dengan nama file yang akan digunakan untuk output sementara argumen berikutnya (largefile
) diproses. Theawk
Program akan mencetak semua baris ke file yang ditentukan oleh variabelout
({print >out}
). Jika polaXYZ
akan ditemukan, variabel output akan didefinisikan ulang untuk menunjuk ke file baru ({out="file2}"
) yang akan digunakan sebagai target untuk mencetak baris data berikutnya.Referensi:
sumber
Ini adalah pekerjaan untuk
csplit
:akan
s
membagi file, membuat potongan dengan pref
ixfile
dann
jumlah menggunakan satu digit, misalnyafile0
dll. Perhatikan bahwa menggunakan/regex/
akan dibagi, tetapi tidak termasuk baris yang cocokregex
. Untuk memisahkan dan termasuk pencocokan garis,regex
tambahkan+1
offset:Ini menciptakan dua file,
file0
danfile1
. Jika Anda benar-benar membutuhkannya untuk diberi namafile1
danfile2
Anda selalu dapat menambahkan pola kosong kecsplit
perintah dan menghapus file pertama:membuat
file0
,file1
danfile2
tetapifile0
kosong sehingga Anda dapat menghapusnya dengan aman:sumber
Dengan yang modern
ksh
inilah varian shell (yaitu tanpased
) dari salah satused
jawaban berdasarkan di atas:Dan varian lain
ksh
saja (yaitu juga menghilangkancat
):(
ksh
Solusi murni tampaknya cukup performan; pada file uji 2,4 GB dibutuhkan 19-21 detik, dibandingkan dengan 39-47 detik dengan pendekatansed
/cat
berbasis).sumber
read
danprint
- Anda hanya harus membiarkannya untuk menghasilkan sendiri. Performa menjadi lebih baik jika Anda membangun AST toolkit sepenuhnya danksh
menyusun semua builtin - aneh bagi saya yangsed
bukan salah satu dari mereka, sebenarnya. Tetapi dengan hal-hal sepertiwhile <file do
saya kira Anda tidak perlused
begitu banyak ...awk
perform di benchmark Anda? Dan sementara saya cukup yakinksh
kemungkinan akan selalu memenangkan pertarungan ini, jika Anda menggunakan GNUsed
Anda tidak bersikap adil terhadapsed
- GNU yang-u
nbuffered adalah pendekatan yang buruk untuk POSIXLY memastikan offset deskriptor dibiarkan di mana program berhenti itu - seharusnya tidak perlu memperlambat operasi reguler program - buffering baik-baik saja - yangsed
harus Anda lakukan hanyalah mencari deskriptor ketika selesai. Untuk alasan apa pun GNU membalikkan mentalitas itu.while
; pencetakan secara implisit dilakukan sebagai efek samping yang ditentukan dari<##
operator pengalihan. Dan hanya garis yang cocok yang perlu dicetak. (Dengan demikian implementasi fitur shell paling fleksibel untuk dukungan incl./excl.) Suatuwhile
loop eksplisit yang saya harapkan akan lebih lambat secara signifikan (tetapi belum dicentang).head
bukanread
; tampaknya hanya sedikit lebih lambat, tapi itu kode terser:{ head -1 <##XYZ ; { read <##"" ;} >file4 ;} <largefile >file3
.Dengan GNU
sed
Anda harus menggunakan-u
sakelar nbuffered. Sebagian besar lainnyased
seharusnya hanya berfungsi.Untuk membiarkan XYZ keluar ...
sumber
Coba ini dengan sed GNU:
sumber
sed -e '1,/XYZ/{w file1' -e 'd}' large_file > file2
Peretasan yang mudah adalah dengan mencetak ke STDOUT atau STDERR, tergantung pada apakah pola target telah cocok. Anda kemudian dapat menggunakan operator pengalihan shell untuk mengarahkan ulang output yang sesuai. Misalnya, dalam Perl, dengan asumsi file input dipanggil
f
dan dua file outputf1
danf2
:Membuang garis yang cocok dengan pola perpecahan:
Termasuk garis yang cocok:
Atau, cetak ke berbagai pegangan file:
Membuang garis yang cocok dengan pola perpecahan:
Termasuk garis yang cocok:
sumber