2012-05-30 4 views
11

Иногда я получаю CSV-файл, который имеет возврат каретки внутри ячейки. Это не приемлемый формат для программы, которая будет использовать ее в качестве входных данных.Подсчет запятых в строке в bash

Чтобы определить, была ли разделена линия ввода, я решил, что у плохой строки не будет ожидаемого количества запятых. Есть ли bash или другой общий инструмент командной строки unix, который позволит мне считать запятые в строке? Если необходимо, я могу написать программу Python или Perl, но если это возможно, я хотел бы добавить строку или два в существующий сценарий bash, чтобы он сработал, если счет запятой ошибочен. Есть идеи?

+1

Почему вы не можете просто найти возврат каретки и удалить их? –

+1

Я предполагаю, что искатель означает разрывы строк в целом, и «просто их удаление» не будет работать, так как допустимые строки также заканчиваются символом перевода строки. – lanzz

+8

'a, b," c, d, e "' имеет 3 поля, но 4 запятых – Stefan

ответ

29

Газа все, кроме запятых, а затем подсчитать количество символов осталось:

$ echo foo,bar,baz | tr -cd , | wc -c 
2 
5

Чтобы подсчитать, сколько раз появляется запятая, вы можете использовать что-то вроде AWK:

string=(line of input from CSV file) 
echo "$string" | awk -F "," '{print NF-1}' 

Но этого действительно недостаточно, чтобы определить, возвращается ли в нем поле. Поля могут содержать запятые внутри, пока они окружены кавычками.

-2

Просто удалите все символы возврата каретки:

tr -d "\r" old_file > new_file 
+1

Почему downvote? –

+0

downvote, потому что возврат каретки действителен, если он ограничивает записи внутри файла, поэтому их нельзя просто удалить. –

2

Попробуйте Perl:

$ perl -ne 'print [email protected]{[/,/g]},"\n"' 
a 
0 
a,a 
1 
a,a,a,a,a 
4 
+1

Вы можете упростить его скаляр, добавив новую строку: 'print @ {[/,/g]}. "\ n" ' –

+1

Использование perl - это ... интересный выбор. Если бы я собирался использовать perl, я бы подумал: «perl -F, -anE» сказать $ # F''. Но это новое решение ... так +1! –

+0

@WilliamPursell +2 за то, что он мастер Perl ;-) – ceving

4

В чистом Баш:

while IFS=, read -ra array 
do 
    echo "$((${#array[@]} - 1))" 
done < inputfile 

или

while read -r line 
do 
    count=${line//[^,]} 
    echo "${#count}" 
done < inputfile 
0

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

csvquote inputfile.csv | wc -l 

и

csvquote inputfile.csv | cut -d, -f1 | csvquote -u 

может быть такая вещь, что вы ищете. См. [https://github.com/dbro/csvquote][1] для кода и дополнительной информации

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