Сценарии оболочки Bash - csv парсинг

34
задан unwind 13 October 2009 в 13:53
поделиться

7 ответов

Первый прототип с использованием старого доброго grep и cut :

grep ${VALUE} inputfile.csv | cut -d, -f${INDEX}

Если это достаточно быстро и дает правильный результат, все готово. :)

28
ответ дан 27 November 2019 в 15:51
поделиться

В файле CSV каждое поле разделяется запятой. Проблема в том, что само поле может иметь встроенную запятую:

Name,Phone
"Woo, John",425-555-1212

Вам действительно нужен пакет библиотеки, который предлагает надежную поддержку CSV, вместо того, чтобы полагаться на использование запятой в качестве разделителя полей. Я знаю, что такие языки сценариев, как Python, имеют такую ​​поддержку. Однако мне хорошо знаком язык сценариев Tcl, поэтому я использую его. Вот простой сценарий Tcl, который выполняет то, о чем вы просите:

#!/usr/bin/env tclsh

package require csv 
package require Tclx

# Parse the command line parameters
lassign $argv fileName columnNumber expectedValue

# Subtract 1 from columnNumber because Tcl's list index starts with a
# zero instead of a one
incr columnNumber -1

for_file line $fileName {
    set columns [csv::split $line]
    set columnValue [lindex $columns $columnNumber]
    if {$columnValue == $expectedValue} {
        puts $line
    }   
}

Сохраните этот сценарий в файле с именем csv.tcl и вызовите его как:

$ tclsh csv.tcl filename indexNumber expectedValue

Пояснение

Сценарий считывает файл CSV построчно и сохраняет строка в переменной $ line, затем она разбивает каждую строку на список столбцов (переменная $ columns). Затем он выбирает указанный столбец и присваивает его переменной $ columnValue. Если есть совпадение, распечатайте исходную строку.

9
ответ дан 27 November 2019 в 15:51
поделиться

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

Так что, если ваши данные достаточно ограничены, можно обойтись простым разделением запятых, сценарий оболочки может сделать это легко. Если, с другой стороны, вам нужно «правильно» проанализировать CSV, то bash не будет моим первым выбором. Вместо этого я бы посмотрел на язык сценариев более высокого уровня, например Python с csv.reader .

12
ответ дан 27 November 2019 в 15:51
поделиться
index=1
value=2
awk -F"," -v i=$index -v v=$value '$(i)==v' file
4
ответ дан 27 November 2019 в 15:51
поделиться

Решение A sed или awk , вероятно, будет короче, но вот решение для Perl:

perl -F/,/ -ane 'print if $F[<INDEX>] eq "<VALUE>"`

где отсчитывается от 0 (0 для первого столбца, 1 для 2-го столбца и т. д.)

2
ответ дан 27 November 2019 в 15:51
поделиться

В качестве альтернативы однострочникам на основе cut - или awk можно использовать специализированный csvtool aka ocaml-csv :

$ cat yourfile | csvtool -t ',' col "$index" - | grep "$value"

Согласно документации, он обрабатывает экранирование, цитирование и т. Д.

46
ответ дан 27 November 2019 в 15:51
поделиться

Использование awk :

export INDEX=2
export VALUE=bar

awk -F, '$'$INDEX' ~ /^'$VALUE'$/ {print}' inputfile.csv

Изменить: Согласно отличному комментарию Денниса Уильямсона , это могло бы быть намного более чисто (и безопасно) написано путем определения переменных awk с помощью переключателя -v :

awk -F, -v index=$INDEX -v value=$VALUE '$index == value {print}' inputfile.csv

Боже ... с переменными и всем остальным, awk почти является настоящим языком программирования ...

8
ответ дан 27 November 2019 в 15:51
поделиться