2016-12-28 1 views
0

у меня есть файл (; отделено) с данными, как этот

Удаление содержимого столбца в зависимости от количества вхождений

111111121;000-000.1;000-000.2 
111111211;000-000.1;000-000.2 
111112111;000-000.1;000-000.2 
111121111;000-000.1;000-000.2 
111211111;000-000.1;000-000.2 
112111111;000-000.1;000-000.2 
121111112;000-000.2;020-000.8 
121111121;000-000.2;020-000.8 
121111211;000-000.2;020-000.8 
121113111;000-000.3;000-200.2 
211111121;000-000.1;000-000.2 

Я хотел бы, чтобы удалить любые $ 3, который имеет менее 3 вхождений, таким образом, результат был бы как

111111121;000-000.1;000-000.2 
111111211;000-000.1;000-000.2 
111112111;000-000.1;000-000.2 
111121111;000-000.1;000-000.2 
111211111;000-000.1;000-000.2 
112111111;000-000.1;000-000.2 
121111112;000-000.2;020-000.8 
121111121;000-000.2;020-000.8 
121111211;000-000.2;020-000.8 
121113111;000-000.3 
211111121;000-000.1;000-000.2 

то есть, только $ 3 были удалены, так как он был только один
вхождение

К сожалению, я не совсем уверен, что (так, как) это можно сделать относительно легко (как это делает совпадение = COUNT.IF, а manuel delete в Excel кажется довольно смущающим)

ответ

0
$ awk -F';' 'NR==FNR{cnt[$3]++;next} cnt[$3]<3{sub(/;[^;]+$/,"")} 1' file file 
111111121;000-000.1;000-000.2 
111111211;000-000.1;000-000.2 
111112111;000-000.1;000-000.2 
111121111;000-000.1;000-000.2 
111211111;000-000.1;000-000.2 
112111111;000-000.1;000-000.2 
121111112;000-000.2;020-000.8 
121111121;000-000.2;020-000.8 
121111211;000-000.2;020-000.8 
121113111;000-000.3 
211111121;000-000.1;000-000.2 

или, если вы предпочитаете:

$ awk -F';' 'NR==FNR{cnt[$3]++;next} {print (cnt[$3]<3 ? $1 FS $2 : $0)}' file file 
+1

Благодарим вас за элегантное решение! (и мне действительно ужасно жаль моего позднего ответа ...) –

0

Вы можете подать файл дважды в awk , При первом запуске вы собрать статистику, которая используется во втором периоде:

script.awk

FNR == NR { stats[ $3 ]++ 
      next 
      } 

      { if(stats[$3] < 3) print $1 $2 
      else print 
      } 

Выполнить это так: awk -F\; -f script.awk yourfile yourfile.

Условие FNR == NR истинно во время обработки первого имени файла, данного awk. Оператор next пропускает второй блок.

Таким образом, второй блок используется только для обработки второго имени файла, данного awk (которое здесь совпадает с первым именем файла).

0

это AWK один вкладыш может помочь, он обрабатывает файл дважды:

awk -F';' 'NR==FNR{a[$3]++;next}a[$3]<3{NF--}7' file file 
+0

YMMV с 'NF -', поскольку это неопределенное поведение для POSIX, поэтому разные awks будут делать с ним разные вещи (скорее всего, игнорируют это или удаляют последнее поле). –

0

Хотя что AWK решения являются лучшими с точки зрения производительность, ваша цель также может быть достигнута примерно с таким:

while IFS=" " read a b;do 
    if [[ "$a" -lt "3" ]];then 
    sed -i "s/$b//" b.txt 
    fi 
done <<<"$(cut -d";" -f3 b.txt |sort |uniq -c)" 

Работа основана на выходе разреза, который учитывает вхождения.

$cut -d";" -f3 b.txt |sort |uniq -c 
     7 000-000.2 
     1 000-200.2 
     3 020-000.8 

Выше работ для редактирования исходного файла на месте, поэтому держите резервную копию для тестирования.