대용량 CSV 파일이 많이 있는데 TSV(탭으로 구분된 형식)로 저장하고 싶습니다. 문제는 CSV 파일의 필드에 쉼표가 있다는 것입니다. 예를 들면 다음과 같습니다.
A,,C,"D,E,F","G",I,"K,L,M",Z
예상 출력:
A C D,E,F G I K,L,M Z
(그 사이의 공백은 "하드" 탭입니다)
이 서버에는 Perl, Python 및 coreutils가 설치되어 있습니다.
답변1
파이썬
이름이 지정된 파일에 추가 csv2tab
하고 실행 가능하게 만듭니다.
touch csv2tab && chmod u+x csv2tab
그것에 추가
#!/usr/bin/env python
import csv, sys
csv.writer(sys.stdout, dialect='excel-tab').writerows(csv.reader(sys.stdin))
시운전
$ echo 'A,,C,"D,E,F","G",I,"K,L,M",Z' | ./csv2tab
A C D,E,F G I K,L,M Z
$ ./csv2tab < data.csv > data.tsv && head data.tsv
1A C D,E,F G I K,L,M Z
2A C D,E,F G I K,L,M Z
3A C D,E,F G I K,L,M Z
답변2
사용csvkit
(파이썬) 예를 들면 다음과 같습니다.
$ csvformat -T in.csv > out.txt
올바른 CSV 및 TSV 인용 및 이스케이프를 스트리밍하고 사용할지 여부
apt 및 기타 패키지 관리자에 있습니다.
답변3
오락을 위해, sed
.
sed -E 's/("([^"]*)")?,/\2\t/g' file
sed
지원하지 않는다면 사용해 -E
보세요 -r
. 리터럴 탭을 sed
지원하지 않는 경우 리터럴 탭을 배치하거나( - \t
in Many Shells ) Bash에서 C 스타일 문자열을 사용해 보세요(이 경우 백슬래시를 두 배로 늘려야 함). 따옴표를 유지하려면 not을 사용하십시오 (이 경우 내부 괄호 쌍은 쓸모가 없으므로 제거할 수 있습니다).ctrlv tab$'...'
\2
\1
\2
또는 를 sed
지원하지 않는 경우 시도해 보세요.-E
-r
sed 's/\("\([^"]*\)"\)\?,/\2\t/g' file
\t
지원되지 않는 경우 위에 제안된 조정 사항을 다시 사용할 수 있습니다.
좀 더 재미있게 보기 위해 Bash의 "here-string" 구문과 동일한 구문을 보여드리겠습니다. sed
우리가 받고자 하는 리터럴 백슬래시가 이제 어떻게 두 배가 되었는지 확인하세요 .
sed $'s/\\("\\([^"]*\\)"\\)\\?,/\\2\t/g' file
이는 큰따옴표 내의 이스케이프된 큰따옴표를 처리하려고 시도하지 않습니다. 일부 CSV 방언은 큰따옴표를 두 배로 묶어 이를 지원합니다(sic).
답변4
진주
perl -lne '
my $re = qr/,(?=(?:[^"]*"[^"]*")*(?![^"]*"))/;
print join "\t", map { s/(?<!\\)"//gr =~ s/\\"/"/gr } split $re;
'
앗
awk -v Q=\" -v FPAT="([^,]*)|(\"[^\"]+\")" -v OFS="\t" '{
for (i=1; i<=NF; ++i)
if ( substr($i, 1, 1) == Q )
$i = substr($i, 2, length($i) - 2)
print $1, $2, $3, $4, $5, $6, $7, $8
}'
결과:
A C D,E,F G I K,L,M Z