我有一个包含大量 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 中的输出重定向不同。这意味着> fn
awk 首先检查文件是否已经打开。如果它已经打开,则 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