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'
여기에서 입력의 따옴표가 균형을 이루고 있다고 가정하면 패턴은 모든 입력과 일치하여 다음과 같이 분류됩니다.
- 인용된 문자열
,
또는 이외의 문자 순서"
- 쉼표
그리고 일치하는 문자열이 쉼표인 경우에만( $1
replace 섹션에 정의되지 않은 경우) 로 대체됩니다 |
.
답변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