Удалить строки на основе дубликатов, описанных регулярным выражением? - PullRequest
0 голосов
/ 01 мая 2018

Допустим, у меня есть файл, подобный этому:

apple   2018-01-01
apple cider 2018-01-05
apple cider 2017-01-06
lemon   2016-12-30
lemon   2017-12-31
lemon juice 2018-03-12
lemon pie 2018-03-30

Т.е. у него есть 1 или более текстовых столбцов, а затем дата. И некоторые текстовые записи дублируются на [разные] даты. Теперь я хочу удалить эти дубликаты:

apple   2018-01-01
apple cider 2017-01-06
lemon   2016-12-30
lemon juice 2018-03-12
lemon pie 2018-03-30

Будь то в одном столбце, можно было бы использовать это решение . Но что, если вместо поиска в определенном столбце я должен искать дубликаты через регулярное выражение? Может ли awk справиться с этим? Или есть какие-то другие обходные пути?

Спасибо.

Ответы [ 2 ]

0 голосов
/ 01 мая 2018

Если предположить, что файл уже отсортирован, то:

  1. Использование rev и uniq:

    rev file | uniq -f1 | rev
    

    Выход:

    apple   2018-01-01
    apple cider 2018-01-05
    lemon   2016-12-30
    lemon juice 2018-03-12
    lemon pie 2018-03-30
    
  2. Если целью является удаление противоположного набора дубликатов, добавьте набор tac с:

    rev file | tac | uniq -f1 | tac | rev
    

    Выход:

    apple   2018-01-01
    apple cider 2017-01-06
    lemon   2017-12-31
    lemon juice 2018-03-12
    lemon pie 2018-03-30
    
  3. Если целью является сохранение самой старой даты:

    rev file | sed 's/ /:/' | rev | sort -t: -k 1,2gr | 
    tr : ' ' | rev | uniq -f1 | rev
    

    Выход:

    apple   2018-01-01
    apple cider 2017-01-06
    lemon   2016-12-30
    lemon juice 2018-03-12
    lemon pie 2018-03-30
    
0 голосов
/ 01 мая 2018

Вы можете сделать это с помощью awk:

awk 'BEGIN{FS="\\s+2"}{a[$1]=2""$2}END{for(i in a){print i,a[i]}}' file.input | sort
apple 2018-01-01
apple cider 2017-01-06
lemon 2017-12-31
lemon juice 2018-03-12
lemon pie 2018-03-30

Это решение сохранится только тогда, когда дубликат появится в последнем появившемся значении. Если вы хотите изменить поведение, вы можете добавить некоторые условия для замены значения, например, если оно более новое.

Вы также можете отсортировать файл перед выполнением операции.

Пояснения:

  • FS="\\s+2 для установки разделителя полей между первым столбцом и датой (я полагаю, что дата начинается с 2)
  • {a[$1]=2""$2} Затем вы создаете массив, где индексы являются первым столбцом, и вы присваиваете значение, когда они появляются.
  • END{for(i in a){print i,a[i]}} просто распечатает результат
...