У меня есть огромный CSV-файл с 10 полями, разделенными запятыми. К сожалению, некоторые строки искажены и не содержат ровно 10 запятых (что вызывает некоторые проблемы, когда я хочу прочитать файл в R). Как я могу отфильтровать только те строки, которые содержат ровно 10 запятых?
9
sed
здесь) только на одно совпадение больше, чем ищется, хотя этот вопрос делает. Вы не должны были закрывать это.grep
ответ там не является приемлемым ответом на любой вопрос ...Ответы:
Еще один POSIX:
Если в строке 10 запятых, то в этой строке будет 11 полей. Поэтому мы просто
awk
используем,
в качестве разделителя полей. Если количество полей равно 11, условиеNF == 11
выполняется, иawk
выполняется действие по умолчаниюprint $0
.источник
-F
устанавливает разделитель полей иNF
ссылается на количество полей в данной строке. Поскольку{statement}
к условию не добавлен ни один блок кодаNF == 11
, действие по умолчанию - печать строки. (@cuonglm, не стесняйтесь включать это объяснение, если хотите.)awk -F , 'NF != 11' <file
-
именем или с именем-
.Используя
egrep
(илиgrep -E
в POSIX):Это отфильтровывает все, что не содержит 10 запятых: оно соответствует полным строкам (
^
в начале и$
в конце), содержащим ровно десять повторений ({10}
) последовательности «любое количество символов, кроме«, », за которым следует один«, »» (([^,]*,)
), за которым снова следует любое количество символов, кроме ',' ([^,]*
).Вы также можете использовать
-x
параметр для удаления якорей:Это менее эффективно , чем cuonglm «ы
awk
решение , хотя; последняя обычно в шесть раз быстрее в моей системе для строк с примерно 10 запятыми. Более длинные линии вызовут огромные замедления.источник
Самый простой
grep
код, который будет работать:Объяснение:
-x
гарантирует, что шаблон должен соответствовать всей строке, а не только ее части. Это важно, чтобы вы не сопоставляли строки с более чем 10 запятыми.-E
означает «расширенное регулярное выражение», что позволяет избежать экранирования обратной косой черты в вашем регулярном выражении.Круглые скобки используются для группировки, а
{10}
впоследствии означает, что в параграфах должно быть ровно десять совпадений в строке шаблона.[^,]
это символ класса, например,[c-f]
будет соответствовать любому символу , который являетсяc
,d
,e
илиf
, и[^A-Z]
будет соответствовать любому символу , который не является прописной буквой. Так что[^,]
соответствует любому отдельному символу, кроме запятой.Класс
*
символов после означает «ноль или более из них».Таким образом, часть регулярного выражения
([^,]*,)
означает «Любой символ, кроме запятой любое количество раз (включая ноль раз), за которым следует запятая», и{10}
указывает 10 из них. Затем,[^,]*
чтобы сопоставить остальные символы без запятой до конца строки.источник
Это сначала разветвляет любую строку с 11 или более запятыми, а затем печатает то, что остается, только те, которые соответствуют 10 запятым.
Видимо, я отвечал на это раньше ... Вот я-плагиат из вопроса, ищущего ровно 4 случая некоторого паттерна:
источник
s/hello/world/2
наs//world/2
, GNU sed работает нормально. С двумяsed
из семейной реликвии,/usr/5bin/posix/sed
поднять segfault,/usr/5bin/sed
идет в бесконечный цикл.sed
иawk
(в комментариях) - мне нравится этот ответ, и я проголосовал за него, но обратите внимание, что перевод принятогоawk
ответа: «Распечатать строки с 11 полями», а перевод этогоsed
ответа: « Попытайтесь удалить 11-ую запятую; в случае неудачи перейдите к следующей строке. Попытайтесь заменить 10-ю запятой на себя; в случае успеха напечатайте строку. "awk
Ответ дает инструкцию к компьютеру так, как вы бы выразить их на английском языке. (awk
подходит для полевых данных.)Бросая коротко
python
:Это прочитает каждую строку и проверит, равно ли число запятых в строке 10
line.count(',') == 10
, если это так, выведите строку.источник
А вот и способ Perl:
-n
Приводитperl
прочитать его входной файл построчно и выполнить сценарий , данный-e
в каждой строке. В-a
очереди на автоматическое расщепление: каждая входная строка будет разделена на значения , даваемого-F
(здесь запятая) и сохраняются в виде массива@F
.$#F
(Или, в более общем случае$#array
), самый высокий индекс массива@F
. Поскольку массивы начинаются с0
, строка с 11 полями будет иметь@F
оф10
. Таким образом, скрипт печатает строку, если в ней ровно 11 полей.источник
print if @F==11
как массив в скалярном контексте возвращает количество элементов.Если поля могут содержать запятые или символы новой строки, ваш код должен понимать CSV. Пример (с тремя столбцами):
Я полагаю, что большинство решений пока отбрасывают второй и четвертый ряд.
источник