키워드 경계를 사용하여 파일을 분할하는 방법


15

수많은 vcard가 포함 된 vcf 파일이 있습니다.

전망을 위해 vcf 파일을 가져올 때 첫 번째 vcard 만 가져 오는 것 같습니다.

따라서 나는 그들을 나누고 싶다.

vcard로 시작한다고 가정하면

BEGIN:VCARD

그리고 끝

END:VCARD

각 vcard를 자체 파일로 분할하는 가장 좋은 방법은 무엇입니까?

감사

최신 정보

모든 답변에 감사드립니다. 이 성질에 대한 질문과 마찬가지로 고양이를 껍질을 벗기는 다양한 방법이 있습니다. 내가 한 것을 선택한 이유는 다음과 같습니다.

모으다

다음은 각 답변에서 내가 좋아하는 것과 그 중 하나를 선택하게 한 이유를 정리 한 것입니다.

  • csplit:이 방법의 간결함을 정말로 좋아했습니다. 방금 파일 확장자를 설정할 수 있기를 바랍니다.
  • gawk: 내가 요청한 모든 것을했습니다.
  • paralell: 일했다. 그러나 나는 새로운 것을 설치해야했습니다. (또한 내 집 디렉토리에 새로운 / bin 디렉토리를 만들기로 결정했습니다)
  • perl: 연락처 이름을 기준으로 VCF를 생성 한 것이 마음에 들었습니다. 그러나 -o 옵션은 실제로 작동하지 않았습니다.

결론

  • 가장 먼저 갈 perl것이기 때문에
  • 다음은 paralell새로운 것을 설치해야했기 때문입니다
  • 다음은 csplit출력 파일에서 확장명을 만들 수없는 한
  • 따라서이상은 쉽게 사용할 수있는 유틸리티로, 파일 이름을 약간 잘라 내고 변경할 수있을 정도로 다재다능한 상을 수상했습니다. 보너스 보너스 cmp:)

사용해 보셨습니까 -b?
Ignacio Vazquez-Abrams

답변:


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 "쓰기 :", fn} {print $ 0 >> fn; } 'example.vcf
Dan Bennett

@ DanBennett 힌트 주셔서 대단히 감사합니다! 내 답변을 업데이트하고 리디렉션 논리 / 수정 된 리디렉션 관련 메모를 단순화했습니다.
maxschlepzig


5

csplit의 Gnu 버전은 확장을 설정할 수 있습니다-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

나는 Mac을 사용하고 있었고 gcsplit을 대신 사용하는 데 시간이 걸렸지 만 일단이 대답을하면 도움이되었습니다.
Luke Gedeon

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 버전입니다. 유닉스의 경우 파일 이름에 "\"를 추가 한 하위 make_filename을 수정하십시오.
J Dan

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.