Как разобрать CSV файл в Bash?

Я работаю над длинным Bash script. Я хочу читать ячейки из файла CSV в переменные Bash. Я могу разобрать строки и первый столбец, но не любой другой столбец. Вот мой код:


  cat myfile.csv|while read line
  do
    read -d, col1 col2 < <(echo $line)
    echo "I got:$col1|$col2"
  done

Он печатает только первый столбец. В качестве дополнительного теста я попробовал следующее:

read -d, x y < <(echo a,b,)

И $y пуст. Поэтому я попробовал:

read x y < <(echo a b)

И $y - b. Почему?

Ответ 1

Вам нужно использовать IFS вместо -d:

while IFS=, read -r col1 col2
do
    echo "I got:$col1|$col2"
done < myfile.csv

Обратите внимание, что для синтаксического анализа CSV общего назначения вы должны использовать специализированный инструмент, который может обрабатывать поля с кодами с внутренними запятыми, среди других проблем, которые Bash не может обрабатывать сам по себе. Примерами таких инструментов являются cvstool и csvkit.

Ответ 2

На странице man:

-d delim         Первый символ delim используется для завершения ввода строки, вместо новой строки.

Вы используете -d,, который завершит ввод строки в запятой. Он не будет читать остальную часть строки. Поэтому $y пуст.

Ответ 3

Мы можем проанализировать CSV файлы со строками в кавычках и разделенными с помощью say | со следующим кодом

while read -r line
do
    field1=$(echo $line | awk -F'|' '{printf "%s", $1}' | tr -d '"')
    field2=$(echo $line | awk -F'|' '{printf "%s", $2}' | tr -d '"')

    echo $field1 $field2
done < $csvFile

awk разбирает строковые поля на переменные и tr удаляет кавычки.

Немного медленнее, поскольку awk выполняется для каждого поля.

Ответ 4

Если вы хотите прочитать файл CSV с несколькими строками, то это решение.

while IFS=, read -ra line
do 
    test $i -eq 1 && ((i=i+1)) && continue
    for col_val in ${line[@]}
    do
        echo -n "$col_val|"                 
    done
    echo        
done < "$csvFile"