열의 필드 구분자 부분 - Unix 구문 분석 중 오류가 발생했습니다.

열의 필드 구분자 부분 - Unix 구문 분석 중 오류가 발생했습니다.

CSV 파일을 처리하기 전에 열 수를 확인하고 싶습니다. 문제는 일부 필드의 텍스트에도 구분 기호(쉼표)가 나타나서 올바르게 구문 분석할 수 없고 너무 많은 열을 수신한다는 것입니다.

예를 들어:

~new file: 12345~,~125.5~,,,~ example (45), case (20)~,,

7열

  1. ~new file: 12345~
  2. ~125.5~
  3. 비어 있는
  4. 비어 있는
  5. ~ example (45), case (20)~
  6. 비어 있는
  7. 비어 있는

문제는~example (45), case (20)~ 다섯 번째 열의 쉼표입니다.

,;구분 기호를 using으로 교체하려고 시도했지만 sed여러 번 반복해야 합니다.

나는 보다 최적화된 방식으로 여러 사례를 일치시킬 수 있는 일반적인 규칙을 원합니다.

필드 참조 문자 가 ~있습니다( a, b, c, d4개 필드에도 동일 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

설명하다

관련 정보