다른 varchar 배열을 자르지 않고 CSV에서 int 배열 열 자르기

다른 varchar 배열을 자르지 않고 CSV에서 int 배열 열 자르기

다음과 같은 CSV가 있습니다.

details.csv

1,2,3,4,5,2015-07-30 23:17:12,2015-07-30 23:39:12,103.4,104.2,1.2,"{1,2,3}",{NORMAL},1,2,
2,2,6,4,5,2015-07-30 12:17:12,2015-07-30 12:39:12,103.4,104.2,1.8,"{4,5,6,7,8,9}",{BOOKING},1,2,
3,2,3,4,9,2015-07-30 10:17:12,2015-07-30 10:39:12,103.4,104.2,1.9,"{1,9}","{NORMAL,BOOKING}",1,2,

여기서 열 15는 비어 있고 열 12는 단일 값인 경우 따옴표가 없습니다({예약}) 및 여러 값이 있는 경우 따옴표("{예약, 정상}").

여기에서 int 배열이고 고정된 크기가 없는 11개의 열을 삭제하고 싶습니다. 그래서 출력은 다음과 같습니다

mod_details.csv
1,2,3,4,5,2015-07-30 23:17:12,2015-07-30 23:39:12,103.4,104.2,1.2,{NORMAL},1,2,
2,2,6,4,5,2015-07-30 12:17:12,2015-07-30 12:39:12,103.4,104.2,1.8,{BOOKING},1,2,
3,2,3,4,9,2015-07-30 10:17:12,2015-07-30 10:39:12,103.4,104.2,1.9,"{NORMAL,BOOKING}",1,2,

그래서 나는 다음을 시도한다:

sed 's/,"{.*}"//' details.csv > mod_details.csv

하지만 문제는 내가 얻는 결과가

mod_details.csv
1,2,3,4,5,2015-07-30 23:17:12,2015-07-30 23:39:12,103.4,104.2,1.2,{NORMAL},1,2,
2,2,6,4,5,2015-07-30 12:17:12,2015-07-30 12:39:12,103.4,104.2,1.8,{BOOKING},1,2,
3,2,3,4,9,2015-07-30 10:17:12,2015-07-30 10:39:12,103.4,104.2,1.9,1,2,

또한 따옴표가 있기 때문에 값이 여러 개인 열 12 값도 제거합니다. 어떤 도움이라도 대단히 감사하겠습니다. 미리 감사드립니다.

답변1

사실 특별히 어렵지는 않습니다. 다음보다 더 구체적인 패턴을 사용해야 합니다 {.*}.

sed 's/"{\([0-9],\)\+[0-9]}",//' details.csv

답변2

답을 찾는 단계로서 다음 셸 기능이 도움이 될 수 있습니다. 명령줄에서 멋진 "예쁜" 레이아웃으로 CSV를 보기 위해 작성했습니다.

그것에주의를 기울이십시오삭제따옴표로 묶인 쉼표와 따옴표로 묶인 줄 바꿈(및 따옴표로 묶은 큰 따옴표)은 아마도 원하는 것이 아닐 수도 있지만 열을 빠르게 확인하고 올바르게 정렬하는 데 유용합니다.

excel() {
    sed -E -e ':t' -e '/^[^"]*("[^"]*"[^"]*)*$/!{N;s/\n//;bt' -e'}' "$@" |
      awk -F\" -v OFS= 'NF>1 {for (i=2;i<=NF;i+=2) gsub(/,/, "", $i)} 1' |
      sed 's/,/,"/g' | column -ts, | tr -d '"' | less -S
}

답변3

사용csvkit:

$ csvcut -C 11 details.csv
1,2,3,4,5,2015-07-30 23:17:12,2015-07-30 23:39:12,103.4,104.2,1.2,{NORMAL},1,2,
2,2,6,4,5,2015-07-30 12:17:12,2015-07-30 12:39:12,103.4,104.2,1.8,{BOOKING},1,2,
3,2,3,4,9,2015-07-30 10:17:12,2015-07-30 10:39:12,103.4,104.2,1.9,"{NORMAL,BOOKING}",1,2,

답변4

각 행을 "구분 기호로 배열로 분할하는 것이 더 쉬운 방법입니다. 그러면 int 배열은 배열의 요소 1이 되며, 이를 빈 문자열로 설정할 수 있고, 다음 요소(요소 2)에는 끝에 추가 쉼표가 추가되므로 다음에서 시작 부분 문자열을 추출할 수 있습니다. 두 번째 캐릭터가 시작됩니다. 이제 {NORMAL,BOOKING}어떻게든 해당 섹션에 큰따옴표를 반환하는 작업을 처리 해야 합니다 . 분할선을 "구분 기호로 사용하면 행에 필드 3이 있으므로 이 부분도 처리됩니다. 다른 행이라면 더 이상 따옴표가 없으므로 항목 배열에는 인덱스 2 이전의 항목만 포함됩니다. 인덱스 #3이 있으면 이를 참조해야 한다는 것을 알고 있습니다.

Perl의 다음 한 줄은 위에서 설명한 것과 정확히 동일한 작업을 수행합니다.

$ perl -F'"' -lane '$F[1]="";$F[2]=substr($F[2],1);$F[3]= "\"" . $F[3] . "\"" if $F[3];print @F' inpu>
1,2,3,4,5,2015-07-30 23:17:12,2015-07-30 23:39:12,103.4,104.2,1.2,{NORMAL},1,2,
2,2,6,4,5,2015-07-30 12:17:12,2015-07-30 12:39:12,103.4,104.2,1.8,{BOOKING},1,2,
3,2,3,4,9,2015-07-30 10:17:12,2015-07-30 10:39:12,103.4,104.2,1.9,"{NORMAL,BOOKING}",1,2,

관련 정보