Jak podzielić plik przy użyciu granic słów kluczowych


15

Mam plik vcf, który zawiera wiele wizytówek.

Podczas importowania pliku vcf do programu Outlook wydaje się importować tylko pierwszą kartę vcard.

Dlatego chcę je podzielić.

Biorąc pod uwagę, że vcard zaczyna się od

BEGIN:VCARD

i kończy się na

END:VCARD

Jaki jest najlepszy sposób na podzielenie każdej karty vcard na własny plik.

Dzięki

AKTUALIZACJA

Dziękuję za wszystkie odpowiedzi. Podobnie jak w przypadku pytań tego rodzaju, istnieje wiele sposobów na skórowanie kota. Oto powód, dla którego wybrałem ten, który zrobiłem.

PODSUMOWANIE

Oto podsumowanie tego, co podobało mi się w każdej odpowiedzi i co skłoniło mnie do wybrania jednej z nich.

  • csplit: Naprawdę podobała mi się zwięzłość tej metody. Chciałem tylko, żeby mógł ustawić rozszerzenie pliku.
  • gawk: Zrobił wszystko, o co prosiłem.
  • paralell: Pracował. Ale musiałem instalować nowe rzeczy. (postanowił także zrobić nowy / bin katalog w moim katalogu domowym)
  • perl: Podobało mi się, że stworzył vcf na podstawie nazwy kontaktu. Ale opcja -o tak naprawdę nie działała

Wniosek

  • Więc pierwszy był, perlponieważ był trochę zepsuty
  • Następnie paralellmusiałem zainstalować nowe rzeczy
  • Dalej było csplit, ponieważ o ile widzę, nie może tworzyć rozszerzeń plików wyjściowych
  • Nagroda jest więc przyznawana gawk za to, że jest narzędziem łatwo dostępnym i wystarczająco wszechstronnym, że mogę trochę posiekać i zmienić nazwę pliku. cmpRównież znaki bonusowe :)

Próbowałeś użyć -b?
Ignacio Vazquez-Abrams

Odpowiedzi:


11

Możesz użyć awk do zadania:

$ 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

Detale

Linia awk działa w ten sposób: ajest licznikiem, który jest zwiększany w każdej BEGIN:VCARDlinii, a jednocześnie wyjściowa nazwa pliku jest konstruowana za pomocą sprintf (przechowywanego w fn). Dla każdej linii bieżąca linia ( $0) jest dołączana do bieżącego pliku (o nazwie fn).

Ostatni echo $?oznacza, że ​​się cmppowiódł, tzn. Wszystkie pojedyncze pliki skonkatenowane są równe oryginalnemu przykładowi vcf.

Zauważ, że przekierowanie wyjścia w awk działa inaczej niż w powłoce. Oznacza to, że z > fnawk najpierw sprawdza, czy plik jest już otwarty. Jeśli jest już otwarty, dołącza do niego awk . Jeśli tak nie jest, otwiera się i obcina.

Z powodu tej logiki przekierowania musimy jawnie zamknąć niejawnie otwarte pliki, ponieważ w przeciwnym razie wywołanie przekroczyłoby limit otwartych plików w przypadkach, gdy plik wejściowy zawiera wiele rekordów.


Musisz zamknąć plik, aby uniknąć błędu zbyt wielu otwartych plików w awk. stackoverflow.com/questions/32878146/… Zatem polecenie brzmi: gawk '/ BEGIN: VCARD / {close (fn); ++ a; fn = sprintf ("karta_% 02d.vcf", a); drukuj „Pisanie:”, fn} {drukuj 0 $ >> fn; } 'example.vcf
Dan Bennett

@DanBennett Dziękuję bardzo za podpowiedź! Zaktualizowałem swoją odpowiedź, a także uprościłem logikę przekierowań / naprawiono uwagi związane z przekierowaniem.
maxschlepzig


5

Wersja csplit w Gnu może ustawić rozszerzenie - odpowiedź Ignacio, myślę, że jest najbardziej zwięzła, potrzebuje tylko ostatniego ulepszenia, aby uzyskać rozszerzenie - używając formatu „printf”:

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

Oto odpowiedni fragment strony csplitman gnu :

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

Używałem Maca i zajęło mi trochę czasu, aby wymyślić użycie gcsplit, ale kiedy to zrobiłem, ta odpowiedź pomogła mi.
Luke Gedeon,

4

Możesz użyć tego skryptu, aby wykonać zadanie. Nazywa się to split-vcf-file .

Przykładowe użycie

$ 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

Aby uruchomić skrypt:

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

split_vcf.pl to wersja dla systemu Windows. dla unix zmodyfikuj podrobną nazwę_pliku, która dodawała „\” w nazwach plików.
J Dan

4

Korzystając z GNU Parallel możesz:

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

Lub jeśli możesz obalić http://oletange.blogspot.com/2013/10/useless-use-of-cat.html , możesz użyć tego:

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

Zobacz więcej przykładów: http://www.gnu.org/software/parallel/man.html

Obejrzyj filmy wprowadzające: https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1

10 sekund instalacji:

$ (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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.