Подтвердить что ты не робот

Как извлечь один столбец из CSV файла

Если у меня есть файл csv, есть ли быстрый способ bash распечатать содержимое только одного столбца? Можно с уверенностью предположить, что каждая строка имеет одинаковое количество столбцов, но каждое содержимое столбца будет иметь разную длину.

4b9b3361

Ответ 1

Вы можете использовать awk для этого. Измените "$ 2" на нужный вам столбец.

awk -F "\"*,\"*" '{print $2}' textfile.csv

Ответ 2

да. cat mycsv.csv | cut -d ',' -f3 напечатает третий столбец.

Ответ 3

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

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

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

Ответ 4

Приземлился здесь, чтобы извлечь из файла, разделенного вкладкой. Думаю, я бы добавил.

cat textfile.tsv | cut -f2 -s

Где -f2 извлекает 2, ненулевой проиндексированный столбец или второй столбец.

Ответ 5

Многие ответы на эти вопросы велики, а некоторые даже смотрят в угловые случаи. Я хотел бы добавить простой ответ, который может быть использован в повседневной жизни... где вы чаще всего попадаете в эти угловые случаи (например, с помощью пропущенных запятых или запятых в кавычках и т.д.).

FS (полевой разделитель) - это переменная, значение которой неверно пространство. Таким образом, awk по умолчанию разбивает пространство в любой строке.

Таким образом, используя BEGIN (Выполнять перед вводом), мы можем установить это поле для чего угодно...

awk 'BEGIN {FS = ","}; {print $3}'

Вышеприведенный код напечатает третий столбец в файле csv.

Ответ 6

Другие ответы работают хорошо, но поскольку вы попросили решение, используя только оболочку bash, вы можете сделать это:

AirBoxOmega:~ d$ cat > file #First we'll create a basic CSV
a,b,c,d,e,f,g,h,i,k
1,2,3,4,5,6,7,8,9,10
a,b,c,d,e,f,g,h,i,k
1,2,3,4,5,6,7,8,9,10
a,b,c,d,e,f,g,h,i,k
1,2,3,4,5,6,7,8,9,10
a,b,c,d,e,f,g,h,i,k
1,2,3,4,5,6,7,8,9,10
a,b,c,d,e,f,g,h,i,k
1,2,3,4,5,6,7,8,9,10
a,b,c,d,e,f,g,h,i,k
1,2,3,4,5,6,7,8,9,10

И затем вы можете вытащить столбцы (первый в этом примере) следующим образом:

AirBoxOmega:~ d$ while IFS=, read -a csv_line;do echo "${csv_line[0]}";done < file
a
1
a
1
a
1
a
1
a
1
a
1

Итак, здесь происходит несколько вещей:

  • while IFS=, - это означает использование запятой в качестве IFS (Internal Field Separator), которое использует оболочка для определения того, что разделяет поля (блоки текста). Поэтому, говоря, что IFS =, похоже на то, что "a, b" совпадает с "a b", если IFS = "" (что и есть по умолчанию).

  • read -a csv_line; - это говорит, что читайте в каждой строке по одному и создавайте массив, в котором каждый элемент называется "csv_line", и отправляйте его в раздел "do" нашего цикла while

  • do echo "${csv_line[0]}";done < file - теперь мы находимся в фазе "do", и мы говорим echo о 0-ом элементе массива "csv_line". Это действие повторяется в каждой строке файла. Часть < file просто сообщает цикл while, из которого следует читать. ПРИМЕЧАНИЕ: помните, что в bash массивы индексируются 0, поэтому первый столбец является 0-м элементом.

Итак, у вас есть это, вытащив столбец из CSV в оболочке. Другие решения, вероятно, более практичны, но этот чист bash.

Ответ 7

Вы можете использовать GNU Awk, см. в этой статье руководства пользователя. В качестве улучшения для решения, представленного в статье (в июне 2015 года), следующая команда gawk позволяет использовать двойные кавычки в двойных кавычках; двойная кавычка отмечена двумя последовательными двойными кавычками (""). Кроме того, это позволяет пустые поля , но даже это не может обрабатывать многострочные поля. Следующий пример печатает третий столбец (через c=3) textfile.csv:

#!/bin/bash
gawk -- '
BEGIN{
    FPAT="([^,\"]*)|(\"((\"\")*[^\"]*)*\")"
}
{
    if (substr($c, 1, 1) == "\"") {
        $c = substr($c, 2, length($c) - 2) # Get the text within the two quotes
        gsub("\"\"", "\"", $c)  # Normalize double quotes
    }
    print $c
}
' c=3 < <(dos2unix <textfile.csv)

Обратите внимание на использование dos2unix для преобразования возможных разрывов строк в стиле DOS (CRLF, т.е. "\ r\n" ) и кодировки UTF-16 (с байтом), в "\n" и UTF-8 (без байта знак заказа), соответственно. Стандартные CSV файлы используют CRLF в качестве разрыва строки, см. Wikipedia.

Если на входе могут быть многострочные поля, вы можете использовать следующий script. Обратите внимание на использование специальной строки для разделения записей на выходе (так как новая строка разделителя по умолчанию может возникать в записи), Опять же, следующий пример печатает третий столбец (через c=3) textfile.csv:

#!/bin/bash
gawk -- '
BEGIN{
    RS="\0" # Read the whole input file as one record;
    # assume there is no null character in input.
    FS="" # Suppose this setting eases internal splitting work.
    ORS="\n####\n" # Use a special output separator to show borders of a record.
}
{
    nof=patsplit($0, a, /([^,"\n]*)|("(("")*[^"]*)*")/, seps)
    field=0;
    for (i=1; i<=nof; i++){
        field++
        if (field==c) {
            if (substr(a[i], 1, 1) == "\"") {
                a[i] = substr(a[i], 2, length(a[i]) - 2) # Get the text within 
                # the two quotes.
                gsub(/""/, "\"", a[i])  # Normalize double quotes.
            }
            print a[i]
        }
        if (seps[i]!=",") field=0
    }
}
' c=3 < <(dos2unix <textfile.csv)

Существует другой подход к проблеме. csvquote может выводить содержимое файла CSV, модифицированного таким образом, чтобы специальные символы в поле были преобразованы, чтобы обычные инструменты обработки текста Unix могли использоваться для выберите определенную колонку. Например, следующий код выводит третий столбец:

csvquote textfile.csv | cut -d ',' -f 3 | csvquote -u

csvquote может использоваться для обработки произвольных больших файлов.

Ответ 8

[dumb @one pts] $cat > file # Сначала мы создадим базовый CSV
а, б, в, г, д, е, ж, з, I, K
1,2,3,4,5,6,7,8,9,10
а, б, в, г, д, е, ж, з, I, K
1,2,3,4,5,6,7,8,9,10

[dumb @one pts] $awk -F, '{print $1}' файл

1

1

Ответ 9

Мне нужно было правильно разбирать CSV, а не cut/awk и молиться. Я пытаюсь это сделать на Mac без csvtool, но csvtool поставляется с ruby, так что вы можете сделать:

echo "require 'csv'; CSV.read('new.csv').each {|data| puts data[34]}" | ruby

Ответ 10

csvtool col 2 file.csv 

где 2 - интересующий вас столбец

Вы также можете сделать

csvtool col 1,2 file.csv 

сделать несколько столбцов

Ответ 11

Вы не можете сделать это без полного анализатора CSV.

Ответ 12

Интересно, почему ни один из ответов до сих пор не упомянул csvkit.

csvkit - это набор инструментов командной строки для преобразования и работы с CSV

CSVKIT документация

Я использую его исключительно для управления данными CSV и до сих пор я не нашел проблему, которую я не мог решить с помощью cvskit.

Чтобы извлечь один или несколько столбцов из файла cvs, вы можете использовать утилиту csvcut которая является частью набора инструментов. Чтобы извлечь второй столбец, используйте эту команду:

csvcut -c 2 filename_in.csv > filename_out.csv 

csvcut справочная страница

Если строки в csv заключены в кавычки, добавьте символ кавычки с опцией q:

csvcut -q '"' -c 2 filename_in.csv > filename_out.csv 

Установите с помощью pip install csvkit или sudo apt install csvkit.

Ответ 13

Вот пример CSV файла с 2 столбцами

myTooth.csv

Date,Tooth
2017-01-25,wisdom
2017-02-19,canine
2017-02-24,canine
2017-02-28,wisdom

Чтобы получить первый столбец, используйте:

cut -d, -f1 myTooth.csv

f обозначает поле, а d обозначает разделитель

Выполнение вышеуказанной команды приведет к следующему выводу.

Выход

Date
2017-01-25
2017-02-19
2017-02-24
2017-02-28

Чтобы получить только 2-й столбец:

cut -d, -f2 myTooth.csv

И вот выходной вывод

Tooth
wisdom
canine
canine
wisdom
incisor

Другой вариант использования:

Ваш входной файл CSV содержит 10 столбцов, и вы хотите столбцы со 2 по 5 и столбцы 8, используя запятую в качестве разделителя ".

cut использует -f (что означает "поля") для указания столбцов и -d (что означает "разделитель") для указания разделителя. Вы должны указать последнее, потому что некоторые файлы могут использовать пробелы, табуляции или двоеточия для разделения столбцов.

cut -f 2-5,8 -d , myvalues.csv

cut - это командная утилита, и вот еще несколько примеров:

SYNOPSIS
     cut -b list [-n] [file ...]
     cut -c list [file ...]
     cut -f list [-d delim] [-s] [file ...]

Ответ 14

Некоторое время, используя этот код, он не "быстро", если не считать "вырезание и вставка из stackoverflow".

Он использует операторы ${##} и ${%%} в цикле вместо IFS. Он вызывает "err" и "die" и поддерживает только запятую, тире и трубку как символы SEP (все, что мне нужно).

err()  { echo "${0##*/}: Error:" "[email protected]" >&2; }
die()  { err "[email protected]"; exit 1; }

# Return Nth field in a csv string, fields numbered starting with 1
csv_fldN() { fldN , "$1" "$2"; }

# Return Nth field in string of fields separated
# by SEP, fields numbered starting with 1
fldN() {
        local me="fldN: "
        local sep="$1"
        local fldnum="$2"
        local vals="$3"
        case "$sep" in
                -|,|\|) ;;
                *) die "$me: arg1 sep: unsupported separator '$sep'" ;;
        esac
        case "$fldnum" in
                [0-9]*) [ "$fldnum" -gt 0 ] || { err "$me: arg2 fldnum=$fldnum must be number greater or equal to 0."; return 1; } ;;
                *) { err "$me: arg2 fldnum=$fldnum must be number"; return 1;} ;;
        esac
        [ -z "$vals" ] && err "$me: missing arg2 vals: list of '$sep' separated values" && return 1
        fldnum=$(($fldnum - 1))
        while [ $fldnum -gt 0 ] ; do
                vals="${vals#*$sep}"
                fldnum=$(($fldnum - 1))
        done
        echo ${vals%%$sep*}
}

Пример:

$ CSVLINE="example,fields with whitespace,field3"
$ $ for fno in $(seq 3); do echo field$fno: $(csv_fldN $fno "$CSVLINE");  done
field1: example
field2: fields with whitespace
field3: field3

Ответ 15

Вы также можете использовать цикл

IFS=,
while read name val; do
        echo "............................"

        echo Name: "$name"
done<itemlst.csv

Ответ 16

Я думаю, что проще всего использовать csvkit:

Получает 2-й столбец: csvcut -c 2 file.csv

Однако есть также csvtool и, возможно, ряд других инструментов csv bash:

sudo apt-get install csvtool (для систем на основе Debian)

Это вернет столбец с первой строкой, в которой есть "ID". csvtool namedcol ID csv_file.csv

Это вернет четвертый ряд: csvtool col 4 csv_file.csv

Если вы хотите удалить строку заголовка:

csvtool col 4 csv_file.csv | sed '1d'