Удалите повторяющиеся строки на основе начального шаблона с помощью bash

Я пытаюсь удалить дубликаты в списке билетов Jira, которые следуют следующему синтаксису:

XXXX-12345: a description

где 12345 — это шаблон типа [0-9]+, а XXXX — константа. Например, следующий список:

XXXX-1111: a description
XXXX-2222: another description
XXXX-1111: yet another description

должно очищаться так:

XXXX-1111: a description
XXXX-2222: another description

Я пытался использовать sed, но то, что я работал на Mac, не работало на Linux. Думаю, с awk было бы проще, но я не эксперт ни по одному из них.

Я пытался:

sed -r '$!N; /^XXXX-[0-9]+\n\1/!P; D' file

Замена $0 на $1 в принятом ответе на этот связанный с вопрос должна помочь.

Thor 10.12.2020 17:48

Можете ли вы показать свой код попытки?

anubhava 10.12.2020 18:13

@Тор Спасибо! это сработало. Не могли бы вы объяснить мне команду, пожалуйста? Я понимаю идею использования awk '!seen', но я не понимаю, почему $1 или как он идентифицирует шаблон в моем случае использования.

Juan Vega 10.12.2020 19:32

@JuanVega: awk разбивает каждую строку на поля в соответствии с тем, что установлено для FS, по умолчанию это последовательности пробелов и табуляции. Это разбиение устанавливает позиционные переменные $1, $2, ... соответственно, поэтому $1 - это первое поле, до первого пробела/табуляции

Thor 10.12.2020 19:37

@anubhava Я пытался использовать sed -r '$!N; /^XXXX-[0-9]+\n\1/!P; D', так как нашел другой ответ, где он использовался для удаления повторяющихся строк. В исходном ответе вместо XXXX-[0-9]+ было (.*). Но я точно не понимаю, как это работает, потому что это не работает.

Juan Vega 10.12.2020 19:37

@ Тор Хорошо, теперь я понял. Так что в моем случае это работает в основном потому, что после : всегда есть пробел. Поэтому, если я хочу, чтобы это работало, разбивая по первому двоеточию, чтобы избежать строк без пробелов, я должен использовать awk -F ':' '!seen[$1], верно? Я был сбит с толку, потому что при поиске информации я видел варианты использования, в которых использовался 0 долларов вместо 1.

Juan Vega 10.12.2020 19:41

@JuanVega: Вы можете просто использовать awk '!seen[$1]++' file

anubhava 10.12.2020 19:52
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
7
1 039
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Если цифры - единственное, что определяет дубликат, вы можете сделать:

awk -F: '{split($1,arr,/-/); if (seen[arr[2]]++) next} 1' file

Если XXXX всегда один и тот же, вы можете упростить до:

awk -F: '!seen[$1]++' file

Либо печатает:

XXXX-1111: a description
XXXX-2222: another description

Спасибо! Я держу это в уме, если в какой-то момент персонажи изменятся.

Juan Vega 11.12.2020 09:36
Ответ принят как подходящий

Этот простой awk должен получить результат:

awk '!seen[$1]++' file

XXXX-1111: a description
XXXX-2222: another description

Да, в итоге я использовал его, как и предложил @Thor. Спасибо!

Juan Vega 11.12.2020 09:27

Это может сработать для вас (GNU sed):

sed -nE 'G;/^([^:]*:).*\n\1/d;P;h' file
  • -nE включить явную печать и расширенные регулярные выражения.
  • G добавлять уникальные строки из пробела в текущую строку.
  • /^([^:]*:).*\n\1/d Если текущий ключ линии уже существует, удалите его.
  • P в противном случае напечатать текущую строку и
  • h хранить уникальные линии в трюме

Н.Б. Ваше решение sed будет работать (не как есть, а с некоторой настройкой), но только если файлы будут отсортированы по ключу.

sed -E 'N;/^([^:]*:).*\n\1/!P;D' file

Я не добавлял код, но да, я сначала отсортировал строки, прежде чем использовать решение no. Мне любопытно, решение, которое вы предлагаете, мне нужно настроить? Я не эксперт по выражениям регулярных выражений, так что же делает это регулярное выражение, чтобы использовать только часть XXXX-1234 в сравнении?

Juan Vega 11.12.2020 16:00

Спасибо за объяснение!

Juan Vega 11.12.2020 17:27

@JuanVega в регулярном выражении вы можете группировать совпадающие части, заключая их в круглые скобки. Затем вы можете обратиться к этим группам по обратной ссылке, которая нумеруется, начиная с самой левой скобки. например /(aaa)(bbb)\1\2/ будет соответствовать строке aaabbbbaaabbb, а /((aaa)bbb)\1\2/' будет соответствовать строке aaabbbbaaabbbbaaa. Таким образом, регулярное выражение /^([^:]*:).*\n\1/ будет соответствовать одному и тому же ключу дважды, а в приведенном выше решении удалит эту строку. HTH Кстати, первое решение работает отсортировано или не отсортировано, второе только при сортировке

potong 12.12.2020 13:26

Другие вопросы по теме