Извлечение определенных столбцов из файла с разделителями, используя Awk - PullRequest
32 голосов
/ 22 октября 2011

Извините, если это слишком просто. У меня есть CSV-файл, где столбцы имеют строку заголовка (v1, v2 и т. Д.). Я понимаю, что для извлечения столбцов 1 и 2 мне нужно сделать: awk -F "," '{print $1 "," $2}' infile.csv > outfile.csv. Но что, если мне придется извлечь, скажем, столбцы с 1 по 10, с 20 по 25 и 30, 33? Как дополнение, есть ли способ извлечь непосредственно с именами заголовков, а не с номерами столбцов?

Ответы [ 8 ]

52 голосов
/ 22 октября 2011

Я не знаю, можно ли делать диапазоны в awk. Вы можете сделать цикл for, но вам придется добавить обработку, чтобы отфильтровать столбцы, которые вам не нужны. Вероятно, это проще сделать:

awk -F, '{OFS=",";print $1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$20,$21,$22,$23,$24,$25,$30,$33}' infile.csv > outfile.csv

что-то еще, чтобы рассмотреть - и это быстрее и более кратким:

cut -d "," -f1-10,20-25,30-33 infile.csv > outfile.csv

Что касается второй части вашего вопроса, я, вероятно, написал бы скрипт на perl, который знает, как обрабатывать строки заголовков, анализировать имена столбцов из stdin или файла и затем выполнять фильтрацию. Это, вероятно, инструмент, который я хотел бы иметь для других вещей. Я не уверен в том, чтобы делать это в один прием, хотя я уверен, что это можно сделать.

13 голосов
/ 07 ноября 2013

Как уже упоминалось @Tom, подходы cut и awk на самом деле не работают для CSV со строками в кавычках. Альтернативой является модуль для python, который предоставляет инструмент командной строки csvfilter. Он работает как cut, но правильно обрабатывает цитирование в столбце CSV:

csvfilter -f 1,3,5 in.csv > out.csv

Если у вас есть Python (и вы должны), вы можете установить его просто так:

pip install csvfilter

Обратите внимание, что индексирование столбцов в csvfilter начинается с 0 (в отличие от awk, который начинается с $ 1). Больше информации на https://github.com/codeinthehole/csvfilter/

3 голосов
/ 25 октября 2011

Другие ответили на ваш предыдущий вопрос. Для этого:

Как дополнение, есть ли способ извлечения непосредственно с именами заголовков, а не с номерами столбцов?

Я не пробовал, но вы можете сохранить индекс каждого заголовка в хэше, а затем использовать этот хэш, чтобы получить его индекс позже.

for(i=0;i<$NF;i++){
    hash[$i] = i;
}

Затем, позже, используйте его:

j = hash["header1"];
print $j;
3 голосов
/ 22 октября 2011

В других языках есть сокращения для диапазонов номеров полей, но не для awk, вам придется писать свой код как страх; -)

awk -F, 'BEGIN {OFS=","} { print $1, $2, $3, $4 ..... $30, $33}' infile.csv > outfile.csv

В awk нет прямой функции для использованияимена полей в качестве спецификаторов столбцов.

Надеюсь, это поможет.

2 голосов
/ 22 октября 2011

Вы можете использовать цикл for для адресации поля с $ i :

ls -l | awk '{for(i=3 ; i<8 ; i++) {printf("%s\t", $i)} print ""}'
1 голос
/ 04 апреля 2015

Tabulator - это набор инструментов командной строки Unix для работы с CSV-файлами, имеющими строки заголовка.Вот пример для извлечения столбцов по имени из файла test.csv:

name,sex,house_nr,height,shoe_size
arthur,m,42,181,11.5
berta,f,101,163,8.5
chris,m,1333,175,10
don,m,77,185,12.5
elisa,f,204,166,7

Затем tblmap -k name,height test.csv производит

name,height
arthur,181
berta,163
chris,175
don,185
elisa,166
0 голосов
/ 25 октября 2016

Не используя awk, но самый простой способ сделать это - просто использовать csvtool .У меня были и другие варианты использования csvtool, и он может обрабатывать кавычки или разделители соответствующим образом, если они появляются в самих данных столбца.

csvtool format '%(2)\n' input.csv
csvtool format '%(2),%(3),%(4)\n' input.csv

Замена 2 номером номера эффективно извлечет данные столбца, которые выищем.

0 голосов
/ 31 октября 2015

Если Perl является опцией:

perl -F, -lane 'print join ",",@F[0,1,2,3,4,5,6,7,8,9,19,20,21,22,23,24,29,32]'

-a автоматически разбивает строку на массив @F полей.Индексы начинаются с 0 (не 1, как в awk)
-F, разделитель полей равен

Если ваш CSV-файл содержит запятые в кавычках, полноценные парсеры CSV, такие как Perl Text::CSV_XS, специально созданысправиться с такой странностью.

perl -MText::CSV_XS -lne 'BEGIN{$csv=Text::CSV_XS->new()} if($csv->parse($_)){@f=$csv->fields();print (join ",",@f[0,1,2,3,4,5,6,7,8,9,19,20,21,22,23,24,29,32])}'

В своем ответе я дал более подробное объяснение: парсинг файла csv с использованием gawk

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...