2016-05-08 7 views
2

У меня есть текстовый файл с данными, разделенными на 4 отдельных | В файле есть некоторые проблемы. Эти линии содержат менее 4 труб. Данные в строках проблем не нужны, и я хочу запустить команду в файле, который удаляет любую строку, содержащую менее четырех каналов. Я также хотел бы знать, сколько строк было удалено впоследствии, поэтому, если это можно было бы напечатать на экране после применения команды, которая была бы идеальной.Удалить строки в текстовом файле, которые содержат менее 4-х труб

Образец данных:

865|Blue Moon Club|Havana Project|34d|879 
899|Soya Plates|Dimsby|78a|699 
657|Sherlock 
900|Forestry Commission|Eden Project|68d|864 

Желаемый результат:

865|Blue Moon Club|Havana Project|34d|879 
899|Soya Plates|Dimsby|78a|699 
900|Forestry Commission|Eden Project|68d|864 

Я попытался awk '|>=3' file.txt, который не работал. Существует много информации о awk, некоторые из которых я нашел, но есть так много, что трудно найти именно то, что я хочу сделать из-за его чистого объема.

+0

Я пробовал awk '|> = 3' file.txt, но это не сработало – neilH

+0

Пример данных и желаемый результат добавлен – neilH

+1

См. [Удалить строку, которая имеет более X столбцов в csv] (http://stackoverflow.com/q/29411952/3776858) – Cyrus

ответ

7

Для устранения линий:

grep '|.*|.*|.*|' file > newfile 

Чтобы подсчитать количество плохих линий:

grep -cv '|.*|.*|.*|' file 

Это не делает редактирование на месте; вы можете сделать это с помощью sed, но часто бывает безопаснее делать такие изменения в новом файле, чтобы избежать потери данных, если вы допустили ошибку.

Первый шаблон grep соответствует любой строке с четырьмя символами трубы. (По умолчанию, grep использует «Basic» регулярные выражения, в которых вы должны написать оператор альтернативы \|. Таким образом, вы можете использовать | как обычный символ.)

Вторых отсчеты Призыва (-c) число не- соответствие (-v) линий.

Вот простое решение СЕПГ:

sed -n -i.bak '/|.*|.*|.*|/p' file 

Опция -n отключает автоматическую печать, поэтому команда выводит только строки, которые соответствуют шаблону. (Опять же, по умолчанию sed использует основные регулярные выражения.). Опция -i.bak делает редактирование на месте, создавая резервную копию оригинала с именем file.bak.

Если вы хотите, чтобы выбрать строки с точно четыре трубы, можно использовать awk:

awk -F'|' 'NF==5' file > newfile 

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

Полезный инструмент для подсчета строк является wc:

wc -l file 

покажет вам, сколько строк в файле; если вы подсчитаете строки как в file, так и в newfile, разница будет, очевидно, числом удалений.Вы можете сделать это вычисление в AWK, тоже, но это немного wordier:

awk -F'|' 'NF==5{print;next}{del+=1}END{print del >>"/dev/stderr"}' file > newfile 
+0

Портативный способ печати на stderr в awk - 'awk '... END {print del | "Кошка> & 2"} ' '. –

2

Это будет делать:

sed -i.bak '/\([^|]*|\)\{4\}/!d' file 

Или (как Cyrus's comment)

sed -i.bak -E '/(\|[^\|]*){4}/!d' file 

Или

sed -n '/^[^|]*|[^|]*|[^|]*|[^|]*|$/p' file > newfile 

или

sed -e '/^[^|]*|[^|]*|[^|]*|$/d' \ 
    -e '/^[^|]*|[^|]*|$/d' \ 
    -e '/^[^|]*|$/d' \ 
    -e '/^[^|]*$/d' \ 
    -i.bak file 

Это не даст вам количество строк. Чтобы получить количество строк запустить grep -cv '^[^|]*|[^|]*|[^|]*|[^|]*|$' file на исходном файле как rici упоминалось, или сравнить номер строки до и после того, как с wc -l file команды


Пояснение:

Первые два sed матчи свободно 4 трубы (не менее но может быть больше), а третий соответствует точно 4 | (не более или менее).

Четвертый sed соответствует точно 3,2,1 и 0 трубам (|) и удаляет эти строки (на месте) и подготавливает файл резервной копии (file.bak) оригинала.

+1

или с GNU sed: 'sed -E '/ (\ | [^ \ |] *) {4} /! D' file' – Cyrus

+0

@Cyrus: Я не был уверен, что регулярное выражение типа' ([ab] *) * 'действительно работает с sed. спасибо, что указали это. – Jahid