CSV 파일에 열을 삭제하는 명령줄 철자가 있습니까?

CSV 파일에 열을 삭제하는 명령줄 철자가 있습니까?

다음 내용의 파일이 있습니다.

1111,2222,3333,4444
aaaa,bbbb,cccc,dddd

원본과 동일하지만 n = 2(또는 3일 수 있음)와 같은 n번째 열이 없는 파일을 얻으려고 합니다.

1111,2222,4444
aaaa,bbbb,dddd

또는 n = 0인 경우(또는 1일 수 있음)

2222,3333,4444
bbbb,cccc,dddd

실제 파일은 수만 개의 열로 구성된 길이가 기가바이트에 달할 수 있습니다.

이런 경우에는 항상 그렇듯이 명령줄 마술사가 우아한 솔루션을 제공할 수 있을 것 같습니다... :-)

실제 실제 사례에서는 첫 번째 열 2개를 삭제해야 하는데, 이는 첫 번째 열을 연속해서 두 번 삭제하여 수행할 수 있지만 조금 일반화하는 것이 더 흥미로울 것이라고 생각합니다.

답변1

나는 이것이 GNU coreutils에서 잘라내는 데에만 해당된다고 생각합니다.

$ cut --complement -f 3 -d, inputfile
1111,2222,4444
aaaa,bbbb,dddd

일반적으로 -f를 통해 원하는 필드를 지정하지만 --complement를 추가하면 자연스럽게 의미가 반전됩니다. '맨컷' 중에서:

--complement
    complement the set of selected bytes, characters or fields

한 가지 주의 사항: 열에 쉼표가 포함되어 있으면 컷이 잘립니다. 컷은 스프레드시트와 같은 방식의 CSV 파서가 아니기 때문입니다. 많은 파서는 CSV에서 이스케이프 쉼표를 처리하는 방법에 대해 서로 다른 아이디어를 가지고 있습니다. 간단한 CSV 사례의 경우 명령줄에서는 여전히 cut을 사용하는 것이 좋습니다.

답변2

데이터가 단순히 쉼표로 구분된 열로 구성된 경우:

cut -d , -f 1-2,4-

awk를 사용할 수도 있지만 필드를 지우는 것은 쉽지만 구분 기호를 제거하려면 약간의 작업이 필요하기 때문에 약간 어색합니다. 빈 필드가 없다면 그다지 나쁘지 않습니다.

awk -F , 'BEGIN {OFS=FS}  {$3=""; sub(",,", ","); print}'

올바르게 인용하면 필드 안에 쉼표가 나타날 수 있는 실제 CSV가 있는 경우실제 CSV 라이브러리.

답변3

CSV 인식 도구를 사용하여 헤더 없는 CSV 입력 파일에서 첫 번째 두 열을 제거합니다.

$ cat file
1111,2222,3333,4444
aaaa,bbbb,cccc,dddd
$ mlr --csv -N cut -x -f 1,2 file
3333,4444
cccc,dddd

작업 -x에 대한 옵션cut밀러( mlr)는 작업을 수행합니다.들어오지 못하게 하다명명된 필드(이 경우 필드 번호 1과 2) CSV 데이터에 헤더가 있었다면 명명된 필드를 사용할 수 있었을 것입니다 -f( -N이 시나리오에서는 옵션도 삭제해야 합니다).

Miller는 CSV를 인식하므로 쉼표, 따옴표 및 개행 문자가 포함된 적절하게 인용된 필드를 처리합니다.

답변4

인덱스를 사용하여 열을 삭제하려면 아래 명령을 사용해 보세요.

dropColumnCSV --index=0 --file=file.csv

다음과 같이 열을 쉼표로 구분하면 작동합니다.sed명령은 함수 내부에서 문자열을 제거하는 데 사용됩니다.

dropColumnCSV() {
  # argument check
  while [ $# -gt 0 ]; do
    case "$1" in
      --index=*)
        index="${1#*=}"
        ;;
      --file=*)
        file="${1#*=}"
        ;;
      *)
        printf "* Error: Invalid argument. *\n"
        return
    esac
    shift
  done

  # file check
  if [ ! -f $file ]; then
        printf "* Error: $file not found.*\n"
        return
  fi

  # sed remove command index zero
  if [[ $index == 0 ]]; then
    sed -i 's/\([^,]*\),\(.*\)/\2/' $file

  # sed remove command index greater than zero
  elif [[ $index > 0 ]]; then
    pos_str=$(for i in {1..$(seq "$index")}; do echo -n '[^,]*',; done| sed 's/,$//') ;
    sed -i 's/^\('$pos_str'\),[^,]*/\1/' $file
  fi
}

관련 정보