Роздрукуйте рядок лише у тому випадку, якщо наступний рядок НЕ містить певного збігу


12

Я намагаюся шукати файл журналу для зареєстрованих дій, які не завершилися. Наприклад, я реєструю "Початок діяльності для ідентифікатора 1234 ...", і якщо буде успішним, наступним рядком буде "Діяльність 1234 завершена".

Я намагаюся отримати рядки "Починаючи ...", які НЕ супроводжуються відповідними рядками "Завершені".

Приклад файлу журналу

Starting activity for ID 1234
ID 1234 completed successfully
Starting activity for ID 3423
ID 3423 completed successfully
Starting activity for ID 9876
ID 9876 completed successfully
Starting activity for ID 99889
ID 99889 completed successfully
Starting activity for ID 10011
ID 10011 completed successfully
Starting activity for ID 33367
Starting activity for ID 936819
ID 936819 completed successfully

У цьому прикладі я б шукав вихід:

Starting activity for ID 33367

... тому що за ним не йде "завершений" рядок.

Я намагався зробити це з grepі awk, але не мав великого успіху. Я припускаю, що це можна зробити за допомогою одного з цих інструментів, але мій grepі awkвідбивні не є вдосконаленими.

Шукаєте швидкий і надійний grepабо awkшаблон, щоб дати тут потрібні мені результати.


Я не думаю, що з grep + awk це просто, але чи можна пояснити трохи, чому ти це робиш? Результат усіх запущених дій, наприклад, успіх чи не завершено?
ромашка

@ warl0ck, я шукаю "не закінчено".
PattMauler

Відповіді:


10

Ось awkальтернатива:

awk '
  /^Starting/ { I[$5] = $0                  }
  /^ID/       { delete I[$2]                }
  END         { for (key in I) print I[key] }
' infile

Вихід:

Starting activity for ID 33367

IАсоціативний масив відстежує то , що ідентифікатори були помічені.


Це працює дуже добре, оскільки це, здається, вміщує ситуації, коли рядки журналу "Починаючи ..." та "Завершено ..." не є суміжними / послідовними. Дякую @Thor!
PattMauler

Прошу. Це повинно ефективно працювати з (майже) довільним розміром введення, оскільки воно лише коли-небудь зберігає ідентифікатор, а час пошуку - O (1).
Тор

Приємно. Тільки одне: як я дізнався з @RobertL ( unix.stackexchange.com/a/243550/135943 ), вам не потрібно призначати значення для створення елемента масиву. Тож замість цього I[$5] = 1можна просто використовувати I[$5]. (Вас не хвилює значення, ви просто хочете, щоб елемент існував , і просто його іменування це досягає.)
Wildcard

@Wildcard: Ви маєте рацію, але після розгляду питання про ОП та виводу, подібного до цього, він є більш правильним, щоб запам'ятати весь рядок та вихід, який був наприкінці.
Тор

3
sed '$!N;/\n.*completed/d;P;D' <input

Це призведе до видалення з виходу всіх ліній введення , які не дотримуються лінії , відповідного рядка завершено .


2

Ось як ви могли це зробити за допомогою GNU sed:

sed -r 'N; /([0-9]+)\n\w+\s+\1/d; P; D' infile
  • N читає ще один рядок у простір візерунка.
  • Регекс відповідності перевіряє, чи знайдені однакові ідентифікатори, якщо так, простір шаблону видалено ( d) і цикл перезапущено.
  • Якщо він не збігся, роздрукуйте перший рядок у просторі шаблону ( P) та видаліть його ( D).

Я не бачу нічого розширеного тут ... так -rце не потрібно, правда?
Луї Маддокс

1
@lmmx: Це потрібно, оскільки в іншому випадку потрібно уникнути групи захоплення, і те саме стосується +кількісного показника.
Тор

Ну гаразд! Я змінив його, і мені сказали, що це не потрібно, дякую за уточнення
Луї Маддокс

1

якщо ваша установка підтримує pcregrep, корисним буде варіант multiline (-M).

pcregrep -M -o '\AStarting activity for ID (\d+)\n(?!ID \1)' t.z

Початкова діяльність для ID 33367

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.