큰따옴표 밖의 모든 쉼표를 파이프로 바꾸십시오.

큰따옴표 밖의 모든 쉼표를 파이프로 바꾸십시오.

sed를 사용하여 큰따옴표 이외의 모든 쉼표를 파이프로 바꾸고 싶습니다.

따라서 .csv 파일의 다음 줄은 다음과 같습니다.

John,Tonny,"345.3435,23",56th Street

다음과 같이 변환됩니다.

John|Tonny|"345.3435,23"|56th Street

이 문제를 해결하기 위해 정규식을 도와주실 수 있나요?

답변1

사용csvkit:

$ csvformat -D '|' file.csv
John|Tonny|345.3435,23|56th Street

csvkit의 도구는 복잡한 CVS 파일을 처리하는 방법을 알고 있으며 여기서는 csvformat구분 쉼표를 올바른 방법으로 바꿉니다 |. 출력 필드는 필요에 따라 참조됩니다.

예:

$ cat file.csv
John,Tonny,"345.3435,23",56th Street
The | factory,Ltd.,"0,0",meep meep

$ csvformat -D '|' file.csv
John|Tonny|345.3435,23|56th Street
"The | factory"|Ltd.|0,0|meep meep

답변2

sed이 옵션을 지원하는 경우 -E( -r일부 구현에서):

sed -Ee :1 -e 's/^(([^",]|"[^"]*")*),/\1|/;t1' < file

이것

:label
   s/pattern/replacement/
t label

매우 일반적인 sed관용어입니다. 성공하는 한 루프에서 동일한 교체를 계속 수행합니다.

여기서는 "0개 이상의 따옴표로 묶인 문자열 또는 문자(에서 캡처됨) 이외의 문자로 구성된 행의 앞부분을 해당 캡처 및 a로 대체합니다. 따라서 귀하의 예에서는 다음을 의미합니다.,\1,\1|

  • John,Tonny,"345.3435,23",56th Street->John|Tonny,"345.3435,23",56th Street
  • John|Tonny,"345.3435,23",56th Street->John|Tonny|"345.3435,23",56th Street
  • John|Tonny|"345.3435,23",56th Street->John|Tonny|"345.3435,23"|56th Street
  • 패턴이 더 이상 일치하지 않으므로 여기서 중지합니다.

를 사용하려면 perl플래그를 다음으로 바꾸면 됩니다 g.

perl -pe 's{("[^"]*"|[^",]+)|,}{$1 // "|"}ge'

여기에서 입력의 따옴표가 균형을 이루고 있다고 가정하면 패턴은 모든 입력과 일치하여 다음과 같이 분류됩니다.

  • 인용된 문자열
  • ,또는 이외의 문자 순서"
  • 쉼표

그리고 일치하는 문자열이 쉼표인 경우에만( $1replace 섹션에 정의되지 않은 경우) 로 대체됩니다 |.

답변3

펄을 사용하여

perl -MText::CSV -lne '
  BEGIN { $p = Text::CSV->new() } 
  print join "|", $p->fields() if $p->parse($_)
' file.csv
John|Tonny|345.3435,23|56th Street

답변4

Python 및 csv모듈 사용:

import csv,sys

with open(sys.argv[1]) as csvfile:
    csvr = csv.reader(csvfile)
    for line in csvr:
        dup = map( lambda x: '"' + x + '"' if ',' in x else x, line )
        print('|'.join(dup))

작동 방식은 다음과 같습니다.

$ python3 csvfile.py  input.csv 
John|Tonny|"345.3435,23"|56th Street
John|Doe|"123.456,25"|26th Street
Jane|Doe|"987.654,52"|15th Street

관련 정보