Есть ли в командной строке заклинание для удаления столбца в CSV-файле?

32

Имея файл следующего содержания:

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 первых столбца, что можно сделать, отбросив первый столбец дважды в последовательности, но я полагаю, что было бы интереснее немного обобщить.

Иван
источник
Поля гарантированно не содержат ,? (Т.е. ,используется только как разделитель полей.)
CVn
@ MichaelKjörling, было бы неплохо иметь более гибкое решение, но в моем случае - да: разделитель есть, ,и он никогда не встречается внутри поля.
Иван
В этом случае ответ Скотта должен быть именно таким.
CVn

Ответы:

47

Я считаю, что это специально для вырезания из 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 по-прежнему путь.

Скотт МакКлюнг
источник
4
Это прекрасно работает, если это простой файл CSV. Если какой-либо из столбцов является строкой с запятой, он будет сброшен, cutпотому что это не анализатор CSV. Если поле CSV имеет разделитель полей в своем значении, оно заключено в кавычки. Кстати, на предмете cut, -fпринимает диапазоны поля. cut -f, -d3-выведет третье поле, удалив первые два.
Алексиос
2
Вы имеете в видуcut -d, -f3-
Бесполезный
@ Алексиос, это хороший момент. Я никогда не имел дело с «настоящим» CSV, только с простым подмножеством. Я отредактирую свой ответ, чтобы отразить это.
Скотт МакКлюнг
@ Бесполезно: Черт, да. Это то, что я называю моей «резкой дислексией», снова поражающей. Вздох . Скотт: CSV файлы - хитрые звери. Слишком много разных субформатов, некоторые из которых даже не являются C SV, но все равно условно называются так.
Алексиос
Это выводит новый CSV на мой терминал - как мне заставить его перезаписать ввод (или, возможно, записать в новый файл, кажется, что OP тоже искал)?
Макс Генис
12

Если данные просто состоят из столбцов, разделенных запятыми:

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

Вы также можете использовать awk, но это немного неловко, потому что очистка поля проста, удаление разделителя требует некоторой работы. Если у вас нет пустого поля, это не так уж плохо:

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

Если у вас есть настоящий CSV, где запятые могут появляться внутри полей, если они правильно указаны, вам нужно настоящая библиотека CSV .

Жиль "ТАК - перестань быть злым"
источник