Як розділити файл за допомогою меж ключових слів


15

У мене є файл vcf, який містить численні візитні картки.

Під час імпорту файлу vcf у outlook, схоже, імпортується лише перша vcard.

Тому я хочу їх розділити.

Враховуючи, що візитка починається з

BEGIN:VCARD

і закінчується с

END:VCARD

Який найкращий спосіб розділити кожну візитку на власний файл.

Спасибі

ОНОВЛЕННЯ

Дякую за всі відповіді. Як і у запитань подібного характеру, існують різні способи шкіри шкіри кішки. Ось міркування, чому я вибрав саме те, що я зробив.

КРУГЛО-Вгору

Ось перелік того, що мені сподобалось у кожній відповіді і що змусило мене вибрати одну з них.

  • csplit: Мені дуже сподобалася стислість цього методу. Я просто хотів, щоб вона могла також встановити розширення файлу.
  • gawk: Це зробило все, про що я просив.
  • paralell: Працював. Але мені довелося встановлювати нові речі. (Він також вирішив зробити новий / бін dir в моєму домашньому режисері)
  • perl: Мені сподобалось, що він створив vcf на основі імені контакту. Але варіант -o насправді не працював

Висновок

  • Тож перше, що пішло, було perlтому, що воно було трохи зламане
  • Далі було paralellтому, що мені довелося встановлювати нові речі
  • Далі було csplit, тому що, наскільки я бачу, він не може створювати розширення на вихідних файлах
  • Таким чином, нагорода перебуває на високому рівні, тому що вона є доступною утилітою та достатньо універсальною, що я можу трохи порубати та змінити ім’я файлу. Бонусні позначки cmpтеж :)

Ви спробували використовувати -b?
Ігнасіо Васкес-Абрамс

Відповіді:


11

Ви можете використовувати awk для роботи:

$ 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

Деталі

Рядок awk працює так: aлічильник, який збільшується в кожному BEGIN:VCARDрядку, і в той же час назву вихідного файлу будується за допомогою sprintf (зберігається в fn). Для кожного рядка поточний рядок ( $0) додається до поточного файлу (названого fn).

Останнє echo $?означає, що cmpфайл був успішним, тобто всі об'єднані окремі файли рівні оригінальному прикладу vcf.

Зверніть увагу, що перенаправлення виводу в awk працює інакше, ніж у оболонці. Це означає, що з > fnawk спочатку перевіряє, чи файл уже відкритий. Якщо він вже відкритий , то AWK приєднує до нього . Якщо його немає, він відкриває і обрізає його.

Через цю логіку перенаправлення нам доведеться явно закрити неявно відкриті файли, оскільки в іншому випадку виклик би досягав ліміту відкритого файлу у випадках, коли вхідний файл містить багато записів.


Вам потрібно буде закрити файл, щоб уникнути занадто багато помилок відкритих файлів. stackoverflow.com/questions/32878146/… Таким чином команда стає: gawk '/ BEGIN: VCARD / {close (fn); ++ a; fn = sprintf ("card_% 02d.vcf", а); друкувати "Написання:", fn} {print $ 0 >> fn; } 'example.vcf
Dan Bennett

@DanBennett Дуже дякую за підказку! Я оновив свою відповідь, а також спростив логіку перенаправлення / фіксовану примітку, пов’язану з перенаправленням.
maxschlepzig


5

Версія Gnu для csplit може встановити розширення - відповідь Ігнасіо, я думаю, найбільш стислий, він просто потребує цього останнього налаштування, щоб отримати розширення - використовуючи формат 'printf':

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

Ось відповідний фрагмент зі сторінки gnu csplitman:

   -b, --suffix-format=FORMAT
          use sprintf FORMAT instead of %02d

Я використовував mac, і мені знадобилося певний час, щоб зрозуміти, як використовувати gcsplit замість цього, але як тільки я зробив цю відповідь, мені допомогли.
Люк Гедеон

4

Ви можете використовувати цей сценарій, щоб виконати роботу. Це називається split-vcf-файл .

Приклад використання

$ 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

Для запуску сценарію:

mkdir vcf_files
split_vcf.pl  -i current.vcf -o vcf_files

split_vcf.pl - це версія Windows. для unix змінити підменю make_filename, яка додала "\" у назви файлів.
J Dan

4

Використовуючи GNU Parallel, ви можете:

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

Або якщо ви можете спростувати http://oletange.blogspot.com/2013/10/useless-use-of-cat.html, ви можете використовувати це замість цього:

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

Дивіться більше прикладів: http://www.gnu.org/software/parallel/man.html

Перегляньте вступні відео: https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1

10 секунд установки:

$ (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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.