Cách chia tệp bằng cách sử dụng ranh giới từ khóa


14

Tôi có một tập tin vcf có chứa nhiều vcards.

Khi nhập tệp vcf để triển vọng, dường như chỉ nhập vcard đầu tiên.

Do đó tôi muốn tách chúng ra.

Cho rằng một vcard bắt đầu bằng

BEGIN:VCARD

và kết thúc bằng

END:VCARD

Cách tốt nhất để chia mỗi vcard thành tập tin riêng của nó là gì.

Cảm ơn

CẬP NHẬT

Cảm ơn vì tất cả những phản hồi. Như với câu hỏi về bản chất này, có nhiều cách khác nhau để lột da một con mèo. Đây là lý do tại sao tôi chọn một trong những tôi đã làm.

VÒNG-LÊN

Đây là một loạt những gì tôi thích từ mỗi câu trả lời và điều gì đã thúc đẩy tôi chọn một trong số chúng.

  • csplit: Tôi thực sự thực sự thích sự đồng nhất của phương pháp này. Tôi chỉ muốn nó cũng có thể thiết lập phần mở rộng tập tin.
  • gawk: Nó đã làm mọi thứ tôi yêu cầu.
  • paralell: Đã làm việc. Nhưng tôi đã phải cài đặt những thứ mới. (nó cũng quyết định tạo một thư mục mới / bin trong thư mục nhà của tôi)
  • perl: Tôi thích rằng nó đã tạo ra vcf dựa trên tên của liên hệ. Nhưng tùy chọn -o không thực sự hoạt động

Phần kết luận

  • Vì vậy, người đầu tiên đi là perlvì nó đã bị hỏng một chút
  • Tiếp theo là paralellvì tôi phải cài đặt những thứ mới
  • Tiếp theo là csplitbởi vì theo như tôi thấy thì nó không thể tạo ra các phần mở rộng trên các tệp đầu ra
  • Vì vậy, giải thưởng được trao cho gawk, vì là một tiện ích có sẵn và đủ linh hoạt để tôi có thể cắt và thay đổi tên tệp một chút. Điểm thưởng cho cmpquá :)

Bạn đã thử sử dụng -b?
Ignacio Vazquez-Abrams

Câu trả lời:


11

Bạn có thể sử dụng awk cho công việc:

$ 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

Chi tiết

Dòng awk hoạt động như thế này: alà bộ đếm được tăng lên trên mỗi BEGIN:VCARDdòng và đồng thời tên tệp đầu ra được xây dựng bằng cách sử dụng sprintf (được lưu trữ trong fn). Đối với mỗi dòng, dòng hiện tại ( $0) được thêm vào tệp hiện tại (được đặt tên fn).

Điều cuối cùng echo $?có nghĩa là cmpđã thành công, tức là tất cả các tệp đơn được nối đều bằng với ví dụ vcf ban đầu.

Lưu ý rằng chuyển hướng đầu ra trong awk hoạt động khác với trong shell. Điều đó có nghĩa là với > fnawk trước tiên hãy kiểm tra xem tệp đã được mở chưa. Nếu nó đã được mở thì awk sẽ thêm vào nó . Nếu không thì nó sẽ mở và cắt nó.

Do logic chuyển hướng này, chúng tôi phải đóng rõ ràng các tệp được mở hoàn toàn, vì nếu không cuộc gọi sẽ đạt giới hạn tệp mở trong trường hợp tệp đầu vào chứa nhiều bản ghi.


Bạn sẽ cần phải đóng tệp để tránh quá nhiều lỗi mở tệp trong awk. stackoverflow.com/questions/32878146/ Từ Vì vậy, lệnh trở thành: gawk '/ BEGIN: VCARD / {close (fn); ++ a; fn = sprintf ("card_% 02d.vcf", a); in "Viết:", fn} {in $ 0 >> fn; } 'example.vcf
Dan Bennett

@DanBennett Cảm ơn bạn rất nhiều vì gợi ý! Tôi đã cập nhật câu trả lời của mình và cũng đơn giản hóa logic chuyển hướng / ghi chú liên quan đến chuyển hướng cố định.
maxschlepzig


5

Phiên bản csplit của Gnu có thể đặt tiện ích mở rộng - Câu trả lời của Ignacio tôi nghĩ là ngắn gọn nhất, nó chỉ cần một chút điều chỉnh cuối cùng để có được tiện ích mở rộng - sử dụng định dạng 'printf':

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

Đây là đoạn trích có liên quan từ trang gnu csplitman:

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

Tôi đã sử dụng mac và phải mất một thời gian tôi mới tìm ra cách sử dụng gcsplit, nhưng một khi tôi đã làm câu trả lời này đã giúp tôi.
Luke Gedeon

4

Bạn có thể sử dụng kịch bản này để thực hiện công việc. Nó được gọi là split-vcf-file .

Ví dụ sử dụng

$ 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

Để chạy tập lệnh:

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

split_vcf.pl là phiên bản windows. đối với unix sửa đổi tên make_filename phụ đã thêm "\" trong tên tệp.
J Dan

4

Sử dụng GNU Parallel bạn có thể làm:

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

Hoặc nếu bạn có thể bác bỏ http://oletange.blogspot.com/2013/10/usless-use-of-cat.html bạn có thể sử dụng điều này thay thế:

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

Xem thêm ví dụ: http://www.gnu.org/software/abul/man.html

Xem video giới thiệu: https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1

Cài đặt 10 giây:

$ (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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.