따옴표를 제외하고 텍스트 파일의 쉼표를 세로선으로 바꿉니다.

따옴표를 제외하고 텍스트 파일의 쉼표를 세로선으로 바꿉니다.

txt 파일이 있습니다.

 ,"Hi, I am Tom",,"16"
"I3","Hi, I am Jerry","Mouse","17"

여기서 파일은 UTF-8입니다. 내가 하고 싶은 것은 따옴표 "" 안의 내용을 제외하고 쉼표를 |로 바꾸는 것입니다. 따라서 새로 생성된 txt 파일은 다음과 같습니다.

|"Hi, I am Tom"||"16"
"I3"|"Hi, I am Jerry"|"Mouse"|"17"

저는 sed나 awk 스크립트에 대해 잘 모르지만 이 작업을 수행하는 데 사용할 수 있다고 들었습니다. 누구든지 그것이 어떻게 완료되었는지 말해 줄 수 있습니까?

답변1

Ed의 의견을 따르고 쉼표 주위의 공백을 수정하면

$ cat text.csv
,"Hi, I am Tom",,"16"
"I3","Hi, I am Jerry","Mouse","17"

$ csvformat -D '|' text.csv
|Hi, I am Tom||16
I3|Hi, I am Jerry|Mouse|17

csvformatcsvkit의 일부입니다: https://csvkit.readthedocs.io/en/1.0.2/scripts/csvformat.html


CSV 모듈은 Ruby와 같이 사용자가 설치했을 수 있는 다른 언어와 함께 제공됩니다.

$ ruby -rcsv -e 'CSV.foreach(ARGV.shift) {|row| puts CSV.generate_line(row, col_sep: "|")}' text.csv
|Hi, I am Tom||16
I3|Hi, I am Jerry|Mouse|17

답변2

이는 일반적인 CSV 문제입니다.awk를 사용하여 csv를 효율적으로 구문 분석하는 가장 강력한 방법은 무엇입니까.

보여주신 입력에 대해서만 \r\n입력 파일에 DOS 줄 끝이 있으므로 필드 구분 기호 쉼표 주위의 공백을 제거하고 RS를 로 설정한 후 FPAT에 GNU awk를 사용합니다.

$ cat -v file
,"Hi, I am Tom",,"16"^M
"I3","Hi, I am Jerry","Mouse","17"^M

$ awk -v RS='\r\n' -v FPAT='[^,]*|"[^"]+"' -v OFS='|' '{NF; $1=$1} 1' file
|"Hi, I am Tom"||"16"
"I3"|"Hi, I am Jerry"|"Mouse"|"17"

이는 NF;gawk 5.0.1의 현재 버그를 해결하기 위한 것입니다.https://lists.gnu.org/archive/html/bug-gawk/2019-11/msg00003.html

물론 이제 스스로에게 물어봐야 합니다. 인용된 필드에 |s, 이스케이프된 큰따옴표( ""또는 ) 또는 개행 문자가 포함된 경우 \"어떻게 해야 할까요 ?

답변3

@RudiC의 아이디어를 확장하면 다음과 같습니다.

awk -v RS='"' -v ORS= '{if(NR % 2){gsub(",","|"); print} else print RS $0 RS}' file

 | "Hi, I am Tom"||"16"
"I3"| "Hi, I am Jerry"|"Mouse"|"17"

이것은 (완료된 방식) "과 같이 두 배로 참조할 때 작동합니다 ."""Hi, I am Tom"", said the DOG"기준CSV), 백슬래시로 이스케이프된 경우는 아닙니다. 인용되지 않은 텍스트와 인용된 텍스트를 번갈아 사용하는 것 외에 파일 형식은 중요하지 않으며 유효한 CSV일 필요는 없습니다.

GNU gawk( gawk)를 사용하면 다음과 같이 단순화할 수 있습니다.

gawk -v RS='"' -v ORS= 'NR % 2 {gsub(",","|")} {print $0 RT}' file

똑같은 것 perl:

perl -pe 'BEGIN{$/=q/"/} s/,/|/ if $. % 2' file

답변4

한 가지 방법은 큰따옴표 안의 쉼표를 텍스트에 사용되지 않은 일부 문자로 변경하고, 다른 모든 쉼표를 대상 문자로 변경한 다음 토큰을 다시 쉼표로 변경하는 것입니다.

$ awk -F'"' '
        {for (i=2; i<=NF; i+=2) gsub (/,/, "\001", $i)
         gsub (/,/, "|")
         gsub (/\001/, ",")
        }
1
' OFS='"' file
 | "Hi, I am Tom"||"16"
"I3"| "Hi, I am Jerry"|"Mouse"|"17"

예제 출력에서도 공백을 제거하는 것 같나요?

관련 정보