如何使用关键字边界分割文件

如何使用关键字边界分割文件

我有一个包含大量 vcard 的 vcf 文件。

将 vcf 文件导入 Outlook 时,似乎只导入第一个 vcard。

因此我想把它们分开。

鉴于 vcard 开头为

BEGIN:VCARD

并以

END:VCARD

将每个 vcard 拆分为自己的文件的最佳方法是什么?

谢谢

更新

感谢您的所有回复。与这种性质的问题一样,剥猫皮的方法有很多种。这就是我选择这个的原因。

围捕

以下是我对每个答案的喜好以及促使我选择其中一个的原因的总结。

  • csplit:我真的很喜欢这种方法的简洁性。我只是希望它也能够设置文件扩展名。
  • gawk: 它完成了我要求的一切。
  • paralell: 工作过。但我必须安装新东西。 (它还决定在我的主目录中创建一个新的 /bin 目录)
  • perl:我喜欢它根据联系人姓名创建 vcf。但 -o 选项并没有真正起作用

结论

  • 所以第一个走的就是perl因为有点破了
  • 接下来是paralell因为我必须安装新东西
  • 接下来是csplit,因为据我所知它无法在输出文件上创建扩展名
  • 因此,奖项授予 gawk,因为它是一款随时可用的实用程序,并且功能多样,我可以稍微修改文件名。还有额外加分cmp:)

答案1

您可以使用 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 中的输出重定向与 shell 中的输出重定向不同。这意味着> fnawk 首先检查文件是否已经打开。如果它已经打开,则 awk附加到它。如果不是,则会打开并截断它。

由于这种重定向逻辑,我们必须明确关闭隐式打开的文件,否则在输入文件包含许多记录的情况下,调用将达到打开文件限制。

答案2

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

答案3

Gnu 版本的 csplit 可以设置扩展名 - Ignacio 的答案我认为是最简洁的,它只需要最后一点调整即可获得扩展名 - 使用“printf”格式:

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

以下是 gnu 手册页中的相关片段csplit

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

答案4

您可以使用此脚本来完成这项工作。它被称为分割 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

相关内容