내 파일: (1개의 샘플 라인)
MMP,"01_janitorial,02_cleaning_tools",1,,CUBIC_INCH,"(14) tray capacity, 6" upright with 3" spacing, mounts on 48"W x 24"D, taupe epoxy, fits MetroMax i
& MetroMax Q shelf, NSF",CLEANING
이것을 7개의 열이 있는 Postgresql 테이블로 읽어야 합니다.
열 분석:
MMP
"01_janitorial,02_cleaning_tools"
1
CUBIC_INCH
"(14) tray capacity, 6" upright with 3" spacing, mounts on 48"W x 1. 24"D, taupe epoxy, fits MetroMax i & MetroMax Q shelf, NSF"
CLEANING
파일은 기본적으로 쉼표로 구분되어 있지만 텍스트가 큰따옴표 안에 있으면 쉼표, 캐리지 리턴(있는 경우) 및 큰따옴표를 무시해야 합니다. 2열과 6열에 표시된 대로입니다.
postgresql 복사 명령을 사용하여 로드하거나 awk, perl, sed 또는 기타 명령을 사용하여 파일을 변환한 다음 로드할 수 있습니다.
답변1
말했듯이 파일이 잘못 생성되었습니다. 하지만 ,
구분 기호 뿐만 아니라 및 를 사용하여 ",
문제를 해결해 볼 수도 있습니다 ,"
. 물론 사용자 정의 스크립팅이 필요하며 여섯 번째 필드에서 비슷한 상황이 발생하지 않을 것이라는 보장은 없습니다.
또는 6번째 필드가 유일하게 손상된 필드라고 가정하고 처음 5개 필드를 제거한 다음 결과에서 마지막 필드와 쉼표를 제거할 수 있습니다. 나머지는 게임 6 콘텐츠입니다.
답변2
일반적으로 단독으로 -F,
는 CSV 파일을 구문 분석하는 데 충분하지 않습니다. 특히 설명한 대로 구분 기호가 인용된 문자열의 일부일 수 있는 경우에는 더욱 그렇습니다. 당신은 그것을 해결할 수 있습니다일부FPAT
필드 구분 기호에 대한 문자를 정의하는 대신 표현식을 사용하여 필드를 정의 awk
하면 여전히 한 줄씩 이동하므로 데이터에서 먼저 줄 바꿈을 사용해야 합니다.
완료되면 다음과 같은 작업을 수행할 수 있습니다 awk 'BEGIN {FPAT="([^,]+)|(\"[^\"]+\")"} { /* normal processing here */ }' /path/to/file
.
표현식은 필드를 "쉼표가 아닌 모든 항목" 또는 "큰따옴표, 큰따옴표가 아닌 하나 이상의 항목, 뒤에 큰따옴표가 오는 항목"으로 정의합니다.
그러나 데이터를 참조하면 폭발합니다.그들 자신큰따옴표가 포함되어 있습니다.
답변3
따옴표가 제대로 이스케이프되지 않기 때문에 솔루션은 데이터 파일에 매우 구체적입니다. 글리치 바가 하나뿐이므로 이는 상당히 가능합니다. 당신을 위한:
#!/bin/bash
while IFS='' read -r line || [[ -n "$line" ]]; do
echo "Line: $line"
# grabbing the first field is easy ..
f1=$(echo $line | cut -d, -f1 )
# now remove the first field from the line
line=$(echo $line | sed "s/$f1,//" )
echo "Line is now: $line"
# to grab the second field use quote as a delimiter
f2=$(echo $line | cut -d\" -f2 )
# now remove the second field from the line
line=$(echo $line | sed "s/\"$f2\",//" )
echo "Line is now: $line"
# fields 3,4,5 are trivial .. just repeat the same pattern as 1 and then remove them
f3=$(echo $line | cut -d, -f1 )
line=$(echo $line | sed "s/$f3,//" )
echo "Line is now: $line"
f4=$(echo $line | cut -d, -f1 )
line=$(echo $line | sed "s/$f4,//" )
echo "Line is now: $line"
f5=$(echo $line | cut -d, -f1 )
line=$(echo $line | sed "s/$f5,//" )
# here is the "trick" ... reverse the string, then you can cut field 7 first!
line=$(echo $line | rev)
echo "Line is now: $line"
f7=$(echo $line | cut -d, -f1 )
# now remove field 7 from the string, then reverse it back
line=$(echo $line | sed "s/$f7,//" )
f7=$(echo $f7 | rev)
# now we can reverse the remaining string, which is field 6 back to normal
line=$(echo $line | rev)
# and then remove the leading quote
line=$(echo $line | cut --complement -c 1)
# and then remove the trailing quote
line=$(echo $line | sed "s/\"$//" )
echo "Line is now: $line"
# and then double up all the remaining quotes
f6=$(echo $line | sed "s/\"/\"\"/g" )
echo f1 = $f1
echo f2 = $f2
echo f3 = $f3
echo f4 = $f4
echo f5 = $f5
echo f6 = $f6
echo f7 = $f7
echo $f1,\"$f2\",$f3,$f4,$f5,\"$f6\",$f7 >> fixed.txt
done < "$1"
작동 방식을 보여주기 위해 많은 출력을 에코하도록 만들었습니다. 이해한 후에는 모든 에코 문을 제거하여 더 빠르게 만들 수 있습니다. 고정된 행을 다음에 추가합니다.고정.txt.
다음은 실행 및 출력의 예입니다.
[root@alpha ~]# ./fixit.sh test.txt
Line: MMP,"01_janitorial,02_cleaning_tools",1,,CUBIC_INCH,"(14) tray capacity, 6" upright with 3" spacing, mounts on 48"W x 24"D, taupe epoxy, fits MetroMax i & MetroMax Q shelf, NSF",CLEANING
Line is now: "01_janitorial,02_cleaning_tools",1,,CUBIC_INCH,"(14) tray capacity, 6" upright with 3" spacing, mounts on 48"W x 24"D, taupe epoxy, fits MetroMax i & MetroMax Q shelf, NSF",CLEANING
Line is now: 1,,CUBIC_INCH,"(14) tray capacity, 6" upright with 3" spacing, mounts on 48"W x 24"D, taupe epoxy, fits MetroMax i & MetroMax Q shelf, NSF",CLEANING
Line is now: ,CUBIC_INCH,"(14) tray capacity, 6" upright with 3" spacing, mounts on 48"W x 24"D, taupe epoxy, fits MetroMax i & MetroMax Q shelf, NSF",CLEANING
Line is now: CUBIC_INCH,"(14) tray capacity, 6" upright with 3" spacing, mounts on 48"W x 24"D, taupe epoxy, fits MetroMax i & MetroMax Q shelf, NSF",CLEANING
Line is now: GNINAELC,"FSN ,flehs Q xaMorteM & i xaMorteM stif ,yxope epuat ,D"42 x W"84 no stnuom ,gnicaps "3 htiw thgirpu "6 ,yticapac yart )41("
Line is now: (14) tray capacity, 6" upright with 3" spacing, mounts on 48"W x 24"D, taupe epoxy, fits MetroMax i & MetroMax Q shelf, NSF
f1 = MMP
f2 = 01_janitorial,02_cleaning_tools
f3 = 1
f4 =
f5 = CUBIC_INCH
f6 = (14) tray capacity, 6"" upright with 3"" spacing, mounts on 48""W x 24""D, taupe epoxy, fits MetroMax i & MetroMax Q shelf, NSF
f7 = CLEANING
다른 방법으로 따옴표를 이스케이프 처리해야 하는 경우 위의 내용을 보면 매우 분명합니다.
답변4
참조 파일에서 캐리지 리턴을 제거하여 최종 제품을 얻었습니다. 스크립트는 다음과 같습니다.
$ cat remove_cr.awk
#!/usr/bin/awk -f
{ record = record $0
# If number of quotes is odd, continue reading record.
if ( gsub( /"/, "&", record ) % 2 )
{ record = record " "
next
}
}
{ print record
record = ""
}