CSV 파일에서 열을 삭제하는 명령줄 주문이 있나요?

CSV 파일에서 열을 삭제하는 명령줄 주문이 있나요?

다음 내용이 포함된 파일:

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

원본과 동일하지만 n번째 열(예: n = 2(또는 3))이 누락된 파일을 얻으려고 합니다.

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

한 가지 참고할 점: 열에 쉼표가 포함되어 있으면 cut이 스프레드시트와 동일한 CSV 파서가 아니기 때문에 cutoff가 발생합니다. 많은 파서는 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
}

관련 정보