CSV 파일을 처리하기 전에 열 수를 확인하고 싶습니다. 문제는 일부 필드의 텍스트에도 구분 기호(쉼표)가 나타나서 올바르게 구문 분석할 수 없고 너무 많은 열을 수신한다는 것입니다.
예를 들어:
~new file: 12345~,~125.5~,,,~ example (45), case (20)~,,
7열
~new file: 12345~
~125.5~
- 비어 있는
- 비어 있는
~ example (45), case (20)~
- 비어 있는
- 비어 있는
문제는~example (45), case (20)~
다섯 번째 열의 쉼표입니다.
,
;
구분 기호를 using으로 교체하려고 시도했지만 sed
여러 번 반복해야 합니다.
나는 보다 최적화된 방식으로 여러 사례를 일치시킬 수 있는 일반적인 규칙을 원합니다.
필드 참조 문자 가 ~
있습니다( a, b, c, d
4개 필드에도 동일 a, ~b, c~, d
하지만 3개 필드 중 하나는 b, c
).
견본:
~new file: 12345~,~125.5~,,,~ example (45), case (20)~,,
~file (54) ~,,~5.5~,,~ this is a sample.~,,~end, end~
~line 3~,~3.6~,~0.0~,~hello~,~hello, world~,~6.7~,~end of line~
예상 출력:
~new file: 12345~;~125.5~;;;~ example (45), case (20)~;;
~file (54) ~;;~5.5~;;~ this is a sample.~;;~end, end~
~line 3~;~3.6~;~0.0~;~hello~;~hello, world~;~6.7~;~end of line~
답변1
이는 쉼표를 필드 구분 기호로 사용하고 물결표를 인용 문자로 사용하는 CSV 파일처럼 보입니다.
Perl 모듈에서 제공하는 것과 같은 올바른 CSV 파서를 사용하십시오 Text::CSV
.
perl -MText::CSV -e 'print scalar(@{Text::CSV->new({quote_char=>"~"})->getline(\*STDIN)})' <file.csv
그러면 CSV 파일의 첫 번째 줄을 읽고 file.csv
그 안에 있는 열 수를 인쇄합니다. 첫 번째 줄을 읽기 위해 인용 문자를 사용하기 전에 물결표 문자임을 이해하는 파서를 인스턴스화합니다. 이 파서의 메서드는 getline()
지정된 파일 핸들에서 행을 읽고 데이터 배열에 대한 참조를 반환합니다(파싱된 각 열에 대해 하나의 항목). 이것은 print scalar(...)
Perl에서 배열의 길이를 인쇄하는 매우 일반적인 방법입니다.
또 다른 방법은CSV 키트명령줄 CSV 파서 툴킷:
csvstat -n -q '~' <file.csv | wc -l
또는 동등하게 긴 옵션을 사용하면
csvstat --names --quotechar '~' <file.csv | wc -l
또한 입력 파일의 첫 번째 줄을 읽고 헤더 목록(CSV 파일의 첫 번째 줄에는 일반적으로 열 헤더가 포함됨)을 한 줄에 하나씩 반환합니다. wc -l
반환된 행 수를 계산합니다 .
명령 csvstat
자체는 ( 없이 wc -l
) 반환됩니다.
1: new file: 12345
2: 125.5
3:
4:
5: example (45), case (20)
6:
7:
나중에 CSV 파일을 구문 분석할 때 다음 방법 중 하나를 사용하거나 가장 편안한 프로그래밍 언어로 적합한 구문 분석기를 찾는 것이 좋습니다. awk
그리고 sed
다음 용도로 사용할 수 있습니다.단순한CSV 데이터이지만 이 경우 데이터는 주의하지 않으면 이러한 도구가 처리하기 어려운 일부 CSV 형식 기능을 사용합니다.
답변2
수정된 질문에 대한 답변:
sed -r 's/(~[^~]*~)?,/\1;/g' infile
~new file: 12345~;~125.5~;;;~ example (45), case (20)~;;
~file (54) ~;;~5.5~;;~ this is a sample.~;;~end; end~
~line 3~;~3.6~;~0.0~;~hello~;~hello, world~;~6.7~;~end of line~
모두를 where ~...~,
로 바꾸는 것은 선택 사항일 수 있습니다.~...~;
~...~
각 행의 열 수를 계산하려면 awk
다음을 수행할 수 있습니다.
awk -F, '{ gsub(/~[^~]*~/,""); print NF }' infile
다음과 같은 입력의 경우:
~new file: 12345~,~125.5~,,,~ example (45), case (20)~,,
,~125.5~,,,~ example (45), case (20)~
다음을 반환합니다.
7
5
에서는 gsub(/~[^~]*~/,"")
a부터 시작하여 다음 패턴까지 빈 문자열로 바꿉니다.~
~
~...~
awk -F, '{ gsub(/~[^~]*~/,""); print $0 }' infile
,,,,,,
,,,,
이는 입력에 내부 아날로그가 없다고 가정합니다 ~
.,~some~thing~,
그러면 print NF
지정된 필드 구분 기호에 따라 필드 수가 인쇄됩니다 -F
.
답변3
,
column
열 구분 기호입니다. 다음과 같이 명령을 실행합니다 .
column -s',' -t -o',' original_data.txt > output.csv
설명하다