텍스트 내용을 CSV로 다시 포맷합니다.

텍스트 내용을 CSV로 다시 포맷합니다.

CSV로 변환하고 싶은 텍스트 파일이 있습니다. 그 내용 형식은 다음과 같습니다.

1 mm/dd/yyyy
LastName, FirstName MiddleName
ID-NUMBER-HERE
GENDER
2 mm/dd/yyyy
LastName, FirstName MiddleName
ID-NUMBER-HERE
GENDER
  • 1번과 2번은 각 그룹의 행 번호입니다. 삭제하고 싶습니다.
  • 날짜는 생일입니다. 다른 형식으로 바꿀 수 있는 방법이 있나요?
  • 이름: 그 사람의 이름이나 접두사가 2개라면 어떻게 되나요? 나는 그것들을 모두 하나의 열에 넣기를 원합니다. 중간 이름과 성에도 마찬가지입니다.

파일 크기는 26MB입니다.

내가 원하는 결과의 형식은 다음과 같습니다.

'yyyy-mm-dd','LastName','FirstName','MiddleName','ID-NUMBER','GENDER'

SED나 다른 도구를 사용하여 이를 수행할 수 있는 방법이 있습니까?

방금 SED에 대해 배웠는데, 제가 직접 하려고 했다면 훨씬 더 오랜 시간이 걸렸을 것입니다.

누구든지 도와줄 수 있나요?

그런데 저는 Mac을 사용하고 있습니다.

감사합니다!

앨빈

답변1

이것은 각 줄을 읽고 이를 필드(@line 배열)로 분할한 다음 @out 배열에 추가하는 Perl 스크립트입니다. @out에 6개의 필드가 있으면 이를 인쇄합니다.

참고: 이는 매우 기본적인 CSV이므로 문자열 등을 따옴표로 묶을 필요가 없습니다. 필드에 필드 구분 기호(예: 쉼표)가 포함되어 있지 않으면 따옴표가 필요하지 않습니다 ,. 고급 CSV의 경우 Text::CSV또는 Perl 모듈을 사용하도록 수정해야 합니다 DBD::CSV.

또한 성, 이름, 중간 이름에는 각각 한 단어만 있다고 가정합니다.

#! /usr/bin/perl

use strict;

my @out = ();
while(<>) {
    my @line = split /,?\s+/;
    my $numfields=@line - 1;
    if ($line[0] =~ m/^\d+$/) {
        push @out, $line[1];
    } elsif ($numfields > 1) {
        push @out, (@line[0..1], join(" ",@line[2..$numfields]));
    } else {
        push @out, @line
    }

    if ( @out == 6 ) { print join(",",@out),"\n" ; @out=() } ;
}

샘플 출력(다음으로 저장된 샘플 입력 사용 input.txt:

$ ./convert-to-csv.pl input.txt 
mm/dd/yyyy,LastName,FirstName,MiddleName,ID-NUMBER-HERE,GENDER
mm/dd/yyyy,LastName,FirstName,MiddleName,ID-NUMBER-HERE,GENDER

답변2

사용 paste:

$ paste -d '|' - - - - <data.in >data.tmp1
$ cat data.tmp1
1 mm/dd/yyyy|LastName, FirstName MiddleName|ID-NUMBER-HERE|GENDER
2 mm/dd/yyyy|LastName, FirstName MiddleName|ID-NUMBER-HERE|GENDER

이제 이것이 있으면 첫 번째 필드의 숫자를 필터링하고 두 번째 필드의 쉼표나 공백을 다음으로 바꿀 수 있습니다 |.

$ awk -F '|' 'BEGIN { OFS=FS } { gsub("^[0-9]* ", "", $1); gsub("[, ]+", "|", $2); print }' data.tmp1 >data.tmp2
$ cat data.tmp2
mm/dd/yyyy|LastName|FirstName|MiddleName|ID-NUMBER-HERE|GENDER
mm/dd/yyyy|LastName|FirstName|MiddleName|ID-NUMBER-HERE|GENDER

날짜 형식을 다시 지정하려면 다음을 수행합니다.

$ awk -F'/' '{ printf("%s-%s-%s\n", $3, $1, $2) }' <( cut -d'|' -f1 data.tmp2 )
yyyy-mm-dd
yyyy-mm-dd

이는 데이터로 대체될 수 있습니다.

$ paste -d '|' \
    <( awk -F'/' '{ printf("%s-%s-%s\n", $3, $1, $2) }' <( cut -d'|' -f1 data.tmp2 ) ) \
    <( cut -d '|' -f 2- data.tmp2 ) >data.tmp3
$ cat data.tmp3
yyyy-mm-dd|LastName|FirstName|MiddleName|ID-NUMBER-HERE|GENDER
yyyy-mm-dd|LastName|FirstName|MiddleName|ID-NUMBER-HERE|GENDER

당신이 가지고 있다면csvkit, 적절하게 인용되고 쉼표로 구분된 CSV로 변환될 수 있습니다.

$ csvformat -d '|' -D ',' -U 2 <data.tmp3
"yyyy-mm-dd","LastName","FirstName","MiddleName","ID-NUMBER-HERE","GENDER"
"yyyy-mm-dd","LastName","FirstName","MiddleName","ID-NUMBER-HERE","GENDER"

위의 솔루션에는 프로세스 대체를 이해하는 쉘이 필요합니다 <(...).

관련 정보