csv를 사용할 때 원치 않는 쉼표(',')로 인해 내 csv 파일이 잘못 표시되어 불일치가 발생합니다.
아래에서 자세히 알아보세요.
내 샘플 CSV 파일:
1|a,b|4
1|c,d|4
1|e,f|4
1|g,h|4
1|i,j|4
내가 원하는 최종 결과는 다음과 같습니다.
1|"a,b"|4
1|"c,d"|4
1|"e,f"|4
1|"g,h"|4
1|"i,j"|4
따옴표를 추가한 후 "|"를 ""로 바꾸면 내 CSV가 예상대로 작동합니다.
아래 명령을 사용했지만 예상대로 제공되지 않습니다.
sed -e 's/,/"&"/' file1.txt
답변1
csvformat
다음에서 사용csvkit
, 최종 결과는 쉼표를 구분 기호로 사용하는 CSV 파일이어야 한다고 가정합니다(질문 텍스트에 명시된 대로).
$ csvformat -d '|' file
1,"a,b",4
1,"c,d",4
1,"e,f",4
1,"g,h",4
1,"i,j",4
이렇게 하면 CSV 파일의 |
형식이 - 문자를 구분 기호로 사용하는 것에서 기본 쉼표를 구분 기호로 사용하는 것으로 다시 지정됩니다. 이렇게 하면 참조해야 하는 필드를 올바르게 참조합니다.
이는 또한 줄 바꿈이 포함된 필드를 올바르게 처리합니다.
$ cat file
1|a,b|4
1|c,d|4
1|e,f|4
1|g,h|4
1|i,j|4
2|"line 1,
line2"|5
$ csvformat -d '|' file
1,"a,b",4
1,"c,d",4
1,"e,f",4
1,"g,h",4
1,"i,j",4
2,"line 1,
line2",5
CSV, JSON, XML, YAML, TOML 등과 같은 구조화된 문서 형식의 문서가 있는 경우에는 이유가 없습니다.아니요해당 문서 형식에 대한 파서를 사용하여 문서를 구문 분석합니다.
답변2
다음을 수행할 수 있습니다.
awk -F'[|]' -v OFS=',' -v q='"' '{ for(i=1; i<=NF; i++) $i=q $i q }1' infile
-F'[|]'
입력 필드 구분자를 정의합니다 . 출력 필드 구분자를 정의합니다
. FS(입력 필드 구분 기호)를 기반으로 각 행/레코드에 필드 수를 결정하므로 필드 수를 반복하고 각 필드에 큰따옴표를 추가하고 해당 행에 최종 업데이트를 인쇄합니다.-v OFS=','
NF
엉뚱한 1
숙어인쇄용.
이 명령은 모든 필드를 참조하므로 유효한 CSV 파일을 갖는 데에는 분명히 문제가 없습니다.
답변3
그리고 sed
:
$ sed 's/[^|]*,[^|]*/"&"/g; y/|/,/' ip.txt
1,"a,b",4
1,"c,d",4
1,"e,f",4
1,"g,h",4
1,"i,j",4
s/[^|]*,[^|]*/"&"/g
다음을 포함하는 모든 필드에 큰따옴표를 추가하세요.,
y/|/,/
모든|
문자를 다음으로 변경하세요.,
그리고 perl
:
perl -F'\|' -lane 'print join ",", map {/,/ ? qq("$_") : $_} @F'
|
이는 입력 필드 구분 기호 로 사용됩니다 . 그러면 map
포함된 모든 필드에 큰따옴표가 추가됩니다 ,
. 마지막으로 join
필드와 문자를 ,
결합하는 데 사용됩니다.
답변4
다른 sed
방법:
sed 's;\([^|]*\)|\([^|]*\)|\(.*\)$;\1,"\2",\3;' data
또는 예를 들어 sed
로드를 지원하는 경우 모든 이스케이프 작업을 피할 수 있습니다.ERE
GNU sed
sed -E 's;([^|]+)\|([^|]+)\|(.+)$;\1,"\2",\3;' data
각 경계에서 중간 그룹만 a로 구분된다는 점을 활용하여 |
길이를 sed
더 짧게 만들 수 있습니다.
sed 's;|\([^|]*\)|;,"\1",;' data
물론 여기에서도 sed가 지원한다면 지루한 탈출 작업을 -E
로드하고 피할 수 있습니다.ERE