Существует ли заклинание командной строки для удаления столбца в 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

Реальный файл может иметь размер в гигабайты и содержать десятки тысяч столбцов.

Как всегда в таких случаях, я подозреваю, что волшебники командной строки могут предложить элегантное решение... :-)

В моем реальном случае мне нужно удалить два первых столбца, что можно сделать, дважды удалив первый столбец подряд, но я полагаю, что было бы интереснее немного обобщить.

решение1

Я считаю, что это относится только к вырезанию из GNU coreutils:

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

Обычно вы указываете нужные поля с помощью -f, но, добавляя --complement, вы, естественно, меняете значение на противоположное. Из 'man cut':

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

Одно предостережение: если какой-либо из столбцов содержит запятую, он выдаст cut off, потому что cut не является парсером 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

Это сработает, если столбцы разделены запятой, как показано ниже.седДля удаления строк внутри функции используются команды.

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
}

Связанный контент