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"
위의 솔루션에는 프로세스 대체를 이해하는 쉘이 필요합니다 <(...)
.