2012-07-03 2 views
1

Я пытаюсь распечатать файл CSV, используя определенные ширины столбцов. Я думаю, что есть одна ошибка с i, из-за которой первый столбец не печатается. Как вы видите, я новичок в Баш и отчаянно пытается сделать это действовать как C.Bash - Распечатать CSV-файл

CSV='./test.csv' 
column_width=(20 6 5 10 10 10 10 8 30) 

IFS="," 
     while read LINE 
     do 
       set -- $LINE 
       arg=([email protected]) 
       for ((i = 0 ; i < ${#arg[@]} ; i++)) 
       do 
         case $i in 
           1) printf "%-20s" ${arg[$i]} ;; 
           2) printf "%-6s" ${arg[$i]} ;; 
           3) printf "%-5s" ${arg[$i]} ;; 
           4) printf "%-10s" ${arg[$i]} ;; 
           5) printf "%-10s" ${arg[$i]} ;; 
           6) printf "%-10s" ${arg[$i]} ;; 
           7) printf "%-10s" ${arg[$i]} ;; 
           8) printf "%-8s" ${arg[$i]} ;; 
           9) printf "%-30s\n" ${arg[$i]} ;; 
         esac 
       done 
     done < $CSV 
     unset IFS 

Я также возникли проблемы поворота случай заявление в петлю. Чтобы не дали никаких результатов, я попытался заменить весь C-стиль для цикла с:

for i in "${arg[@]}"; do 
     printf "%-${column_width[$i]}s" ${arg[$i]} 
done 

Я уверен, что есть лучший способ для достижения этой цели. Я пытаюсь узнать о sed/awk, но я бы хотел знать, как это сделать без них.

+1

Оператор case не охватывает $ i == 0, следовательно, пропускается первый столбец. –

+0

Спасибо. Я мог бы прочитать это более внимательно. – contrapositive

ответ

2
#!/usr/bin/env bash 

csv=./test.csv 
column_width=(20 6 5 10 10 10 10 8 30) 

while n=0; IFS=, read -ra x; do 
    printf '%-*s' {,,,,,,,,}{"${column_width[n]}","${x[n++]}"} 1 $'\n' 
done <"$csv" 
+0

+1 несмотря на Perl-подобную непостижимость. :) Вам нужно сбросить 'n' до 0 для каждой итерации. – chepner

+0

@chepner Спасибо исправлено. Наверное, хорошо, что я не показывал версию, которая имеет дело с различным количеством полей в строке. :) – ormaaj

+0

Это именно то, что я искал; что-то кратким. Это похоже на хорошее использование встроенных команд bash (я, вероятно, не признал бы плохое использование). Пожалуйста, не стесняйтесь публиковать версию с различными полями. – contrapositive

2

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

Поскольку я больше нахожусь во избежание использования скрипта-логики и использования -эдитор-макро-функциональная сторона вещей, вот моя версия.

#!/bin/sh 

CSV='./test.csv' 

while IFS=, read one two three four five six seven eight nine 
do 
    test "$one" && printf %s-20s "$one" 
    test "$two" && printf %s-6s "$two" 
    test "$three" && printf %s-5s "$three" 
    test "$four" && printf %s-10s "$four" 
    test "$five" && printf %s-10s "$five" 
    test "$six" && printf %s-10s "$six" 
    test "$seven" && printf %s-10s "$seven" 
    test "$eight" && printf %s-8s "$eight" 
    test "$nine" && printf %s-30s "$nine" 
    printf \\n 
done < "$CSV" # mind the quoting 

Я лично думаю, что это немного более приятным для глаз (и не bashisms!), Но YMMV. Я бы также избегал обширных тестов, но просто печатал, если это было возможно.

+0

Это более читаемо, чем краткая версия ormaaj, однако «базисы» - это именно то, что я пытаюсь изучить. :) – contrapositive

+0

Я знаю, что я не буду говорить вам, когда я думаю, что вы попросили неправильный ответ или неправильные вопросы, но я думаю, вы действительно должны решить вопрос, который нелегко решить с помощью простого 'sh'- стиль. Когда вы создали такой пример, вы могли бы заметить, что это тоже очень громоздко в bash ;-). Извините за троллинг. –

1

Хорошая работа, Contrapositive.

Ошибка в вашем скрипте из-за того, что индекс массива даже в Bash начинается с 0, тогда как в вашем случае коммутатора нет. Наименьшее изменение, о котором я могу думать, это «сдвинуть» массив arg. Попробуйте использовать arg=(0 [email protected]). Вы можете использовать любое другое значение в 0-м индексе массива. Будет рассмотрен несуществующий случай 0.

Смежные вопросы