Cara membagi file dengan menggunakan batas kata kunci

14

Saya memiliki file vcf yang berisi banyak vcard.

Saat mengimpor file vcf ke outlook sepertinya hanya mengimpor vcard pertama.

Karenanya saya ingin membaginya.

Mengingat bahwa vcard dimulai dengan

BEGIN:VCARD

dan diakhiri dengan

END:VCARD

Apa cara terbaik untuk membagi setiap vcard ke dalam file itu sendiri.

Terima kasih

MEMPERBARUI

Terima kasih atas semua tanggapannya. Seperti halnya pertanyaan semacam ini, ada berbagai cara untuk menguliti kucing. Inilah alasan mengapa saya memilih yang saya lakukan.

PEMBULATAN

Berikut adalah ringkasan dari apa yang saya sukai dari setiap jawaban dan apa yang mendorong saya untuk memilih salah satu dari mereka.

  • csplit: Saya sangat menyukai keringkasan metode ini. Saya hanya berharap itu bisa juga mengatur ekstensi file.
  • gawk: Itu melakukan semua yang saya minta.
  • paralell: Bekerja. Tetapi saya harus menginstal hal-hal baru. (itu juga memutuskan untuk membuat dir / bin baru di dir rumah saya)
  • perl: Saya suka itu membuat vcf berdasarkan nama kontak. Tapi opsi -o tidak benar-benar berfungsi

Kesimpulan

  • Jadi yang pertama pergi adalah perlkarena agak rusak
  • Selanjutnya adalah paralellkarena saya harus menginstal hal-hal baru
  • Selanjutnya adalah csplit, karena sejauh yang saya bisa lihat itu tidak dapat membuat ekstensi pada file output
  • Jadi penghargaan diberikan kepada gawk, karena menjadi utilitas yang sudah tersedia, dan cukup fleksibel sehingga saya dapat memotong dan mengubah nama file sedikit. Tanda bonus cmpjuga :)
denormalizer
sumber
Apakah Anda mencoba menggunakan -b?
Ignacio Vazquez-Abrams

Jawaban:

11

Anda dapat menggunakan awk untuk pekerjaan itu:

$ curl -O https://raw.githubusercontent.com/qtproject/qt-mobility\
/d7f10927176b8c3603efaaceb721b00af5e8605b/demos/qmlcontacts/contents/\
example.vcf

$ gawk ' /BEGIN:VCARD/ { close(fn); ++a; fn=sprintf("card_%02d.vcf", a); 
        print "Writing: ", fn } { print $0 > fn; } ' example.vcf
Writing:  card_01.vcf
Writing:  card_02.vcf
Writing:  card_03.vcf
Writing:  card_04.vcf
Writing:  card_05.vcf
Writing:  card_06.vcf
Writing:  card_07.vcf
Writing:  card_08.vcf
Writing:  card_09.vcf

$ cat card_0* > all.vcf
$ cmp example.vcf all.vcf
$ echo $?
0

Detail

Baris awk bekerja seperti ini: aadalah penghitung yang ditambahkan pada setiap BEGIN:VCARDbaris dan pada saat yang sama nama file keluaran dibangun menggunakan sprintf (disimpan dalam fn). Untuk setiap baris, baris saat ini ( $0) ditambahkan ke file saat ini (dinamai fn).

Yang terakhir echo $?berarti cmpberhasil, yaitu semua file tunggal yang disatukan sama dengan contoh asli contoh vcf.

Perhatikan bahwa redirection output di awk berfungsi berbeda dari pada di shell. Itu artinya dengan > fnawk cek terlebih dahulu apakah file tersebut sudah terbuka. Jika sudah terbuka maka awk menambahkannya . Jika tidak maka itu akan terbuka dan memotongnya.

Karena logika pengalihan ini kita harus secara eksplisit menutup file yang dibuka secara implisit, karena jika tidak panggilan akan mencapai batas file terbuka dalam kasus di mana file input berisi banyak catatan.

maxschlepzig
sumber
Anda harus menutup file untuk menghindari kesalahan file yang terbuka terlalu banyak di awk. stackoverflow.com/questions/32878146/... Jadi perintahnya menjadi: gawk '/ BEGIN: VCARD / {close (fn); ++ a; fn = sprintf ("card_% 02d.vcf", a); cetak "Menulis:", fn} {print $ 0 >> fn; } 'example.vcf
Dan Bennett
@DanBennett Terima kasih banyak atas petunjuknya! Saya telah memperbarui jawaban saya dan juga menyederhanakan logika redirection / memperbaiki redirection notes terkait.
maxschlepzig
11
csplit -f vcard input.txt -z '/END:VCARD/+1' '{*}'
Ignacio Vazquez-Abrams
sumber
5

Versi Gnu dari csplit dapat mengatur ekstensi - Jawaban Ignacio saya pikir paling ringkas, hanya perlu sedikit penyesuaian terakhir untuk mendapatkan ekstensi - menggunakan format 'printf':

csplit -f vcard -b %02d.vcard input.txt -z '/END:VCARD/+1' '{*}'

Berikut cuplikan yang relevan dari csplithalaman man gnu :

   -b, --suffix-format=FORMAT
          use sprintf FORMAT instead of %02d
Keithel
sumber
Saya menggunakan mac dan butuh beberapa saat untuk mencari tahu untuk menggunakan gcsplit sebagai gantinya, tetapi begitu saya melakukannya, jawaban ini membantu saya.
Luke Gedeon
4

Anda dapat menggunakan skrip ini untuk melakukan pekerjaan itu. Ini disebut split-vcf-file .

Contoh penggunaan

$ split_vcf.pl 

Error! Input VCF filename missing,  -i

Usage: perl split_vcf.pl -i input_file -o output_dir [OPTION]

    -v,         Verbosity levels, 1-3

Untuk menjalankan skrip:

mkdir vcf_files
split_vcf.pl  -i current.vcf -o vcf_files
slm
sumber
split_vcf.pl adalah versi windows. untuk unix, modifikasi sub make_filename yang menambahkan "\" pada nama file.
J Dan
4

Menggunakan GNU Parallel yang bisa Anda lakukan:

cat foo.vcf | parallel --pipe -N1 --recstart BEGIN:VCARD 'cat >{#}'

Atau jika Anda dapat menyangkal http://oletange.blogspot.com/2013/10/useless-use-of-cat.html Anda dapat menggunakan ini sebagai gantinya:

< foo.vcf parallel --pipe -N1 --recstart BEGIN:VCARD 'cat >{#}'

Lihat lebih banyak contoh: http://www.gnu.org/software/parallel/man.html

Tonton video intro: https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1

Instalasi 10 detik:

$ (wget -O - pi.dk/3 || lynx -source pi.dk/3 || curl pi.dk/3/ || \
   fetch -o - http://pi.dk/3 ) > install.sh
$ sha1sum install.sh | grep 3374ec53bacb199b245af2dda86df6c9
12345678 3374ec53 bacb199b 245af2dd a86df6c9
$ md5sum install.sh | grep 029a9ac06e8b5bc6052eac57b2c3c9ca
029a9ac0 6e8b5bc6 052eac57 b2c3c9ca
$ sha512sum install.sh | grep f517006d9897747bed8a4694b1acba1b
40f53af6 9e20dae5 713ba06c f517006d 9897747b ed8a4694 b1acba1b 1464beb4
60055629 3f2356f3 3e9c4e3c 76e3f3af a9db4b32 bd33322b 975696fc e6b23cfb
$ bash install.sh
Ole Tange
sumber