キーワード境界を使用してファイルを分割する方法


14

多数のvcardを含むvcfファイルがあります。

Outlookにvcfファイルをインポートすると、最初のvcardのみがインポートされるようです。

したがって、それらを分割したいと思います。

vcardが次で始まることを考えると

BEGIN:VCARD

で終わる

END:VCARD

各vcardを独自のファイルに分割する最良の方法は何ですか。

ありがとう

更新

すべての回答をありがとう。この性質の質問と同様に、猫の皮を剥ぐさまざまな方法があります。ここに私がやったものを選んだ理由があります。

切り上げする

以下に、各回答で気に入ったものと、そのうちの1つを選択するきっかけをまとめました。

  • csplit:この方法の簡潔さが本当に好きでした。ファイル拡張子も設定できるようになりました。
  • gawk:それは私がそれを求めたすべてをした。
  • paralell:働いた。しかし、新しいものをインストールする必要がありました。(また、私のホームディレクトリに新しい/ binディレクトリを作成することにしました)
  • perl:連絡先の名前に基づいてvcfを作成したことが気に入った。しかし、-oオプションは実際には機能しませんでした

結論

  • 最初に行ったのperlは、少し壊れていたからです
  • 次はparalell、新しいものをインストールしなければならなかったからです
  • 次はcsplit、私が見る限り、出力ファイルに拡張子を作成できないためです
  • そのため、賞はgawkに贈られます。これは、すぐに利用でき、ファイル名を少し変更して変更できるほど十分に汎用性のあるユーティリティであるためです。ボーナスマーク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が追加されます。そうでない場合は、開いて切り捨てます。

このリダイレクトロジックのため、暗黙的に開かれたファイルを明示的に閉じる必要があります。そうしないと、入力ファイルに多くのレコードが含まれる場合に呼び出しが開いているファイルの制限に達するからです。


awkで開かれているファイルが多すぎるというエラーを回避するには、ファイルを閉じる必要があります。stackoverflow.com/questions/32878146/… したがって、コマンドは次のようになります。gawk '/ BEGIN:VCARD / {close(fn); ++ a; fn = sprintf( "card_%02d.vcf"、a); print "Writing:"、fn} {print $ 0 >> fn; } 'example.vcf
ダン・ベネット

@DanBennettヒントをありがとうございます!回答を更新し、リダイレクトロジックを簡略化し、リダイレクト関連のメモを修正しました。
maxschlepzig


5

csplitのGnuバージョンは拡張機能を設定できます-Ignacioの答えは最も簡潔だと思います。拡張機能を取得するには、最後の微調整が必​​要です-'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-fileと呼ばれます

使用例

$ 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ダン

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
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.