Проверить, содержит ли файл одинаковый текст в последовательных строках

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

то есть grep... "ошибка" /tmp/file.txt

этот файл будет соответствовать:

2020-01-01 05:05 text1
2020-01-01 05:07 error
2020-01-01 05:15 error
2020-01-01 05:25 error
2020-01-01 05:45 text2

это не будет

2020-01-01 05:05 text1
2020-01-01 05:15 error
2020-01-01 05:25 text2
2020-01-01 05:45 error
2020-01-01 05:05 text3

Есть идеи по использованию grep, sed или awk? В идеале я хотел бы иметь выходное значение 0 для совпадения и 1 для не совпадения.

Вы знаете, как присвоить значение поля переменной в awk?

Ted Lyngmo 28.10.2022 18:33

я не знаком с авк

ansanes 28.10.2022 18:41

«Я не знаком с awk» — тогда зачем помечать вопрос awk?

Ted Lyngmo 28.10.2022 18:44

@Садовник. да, метка времени и любой другой текст игнорируются. Я забыл упомянуть, что соответствующий текст должен быть указан как аргумент.

ansanes 28.10.2022 18:46

То есть вам просто нужен ответ да/нет? Да, где-то в файле, неважно где, данный текст встречается на последовательных строках?

Mark Reed 28.10.2022 18:46
uniq обладает всем необходимым для этого сценария функционалом.
Marek R 28.10.2022 18:47

@TedLyngmo, глядя на некоторые примеры awk, я подозреваю, что это можно сделать с помощью awk. ты не думаешь?

ansanes 28.10.2022 18:47

@МаркРид. Да, но также было бы здорово иметь команду, показывающую совпадающие строки.

ansanes 28.10.2022 18:48

@ansanes Я добавил: «Отметка времени и любой другой текст после третьего поля следует игнорировать при сравнении». к вопросу. Вот как я интерпретировал ваш комментарий выше. Это было правильно?

Ted Lyngmo 28.10.2022 19:06

@TedLyngmo Да.

ansanes 28.10.2022 19:43

@ansanes Хорошо, тогда я не понимаю, как работает принятый ответ, поскольку он включает текст после третьего поля в сравнении.

Ted Lyngmo 28.10.2022 19:45

@TedLyngmo Не совсем понимаю, что вы имеете в виду. Я принял ответ, потому что он указывает в правильном направлении, хотя это не совсем то, о чем я спрашивал в первую очередь.

ansanes 28.10.2022 23:45

@ansanes Я имею в виду именно то, что вы указали. Он не отвечает на то, что вы просили (после моего редактирования, которое прояснило, что вы хотите).

Ted Lyngmo 28.10.2022 23:50
Стоит ли изучать 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 называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
13
100
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Похоже, uniq делает все, что вам нужно.

-д, --повторил
печатать только повторяющиеся строки, по одной для каждой группы

-s, --skip-chars=N
избегать сравнения первых N символов

Так что это должно работать для вас:

uniq --skip-chars=17 -d /tmp/file.txt

Проверено на моей машине:

$ cat in.txt 
2020-01-01 05:05 text1
2020-01-01 05:07 error
2020-01-01 05:15 error
2020-01-01 05:25 error
2020-01-01 05:45 text2

$ uniq --skip-chars=17 -d in.txt 
2020-01-01 05:07 error

Вы можете получить номер первой строки, где он встречается, выполнив cat -n | и отрегулировав значение пропуска, например. cat -n in.txt | uniq -ds 25.

Mark Reed 28.10.2022 19:08

Это работает. Я использую его так: [[ $(uniq --skip-chars=28 -c -d /var/log/file.log | grep "error" | awk '$1 > 2' | wc) > 2 ]] чтобы указать текст, который я ищу, и количество последовательных строк с совпадением.

ansanes 28.10.2022 19:22

Хорошо, теперь вы ввели кучу других требований. uniq -c -d доставит вам только дубликаты со счетом; количество всегда будет не менее 2, но вы ищете те, где оно не менее 3. И затем вы считаете их и ищете файлы, в которых это происходит более двух раз?

Mark Reed 28.10.2022 19:26

FWIW, вам никогда не нужно делать grep | awk. Вместо grep "error" | awk '$1 > 2' можно написать awk '/error/ && $1 > 2'. Но вся эта конструкция кажется излишне окольной.

Mark Reed 28.10.2022 19:27

Вы тоже не хотите [[ ... > 2 ]]; это делает лексическое сравнение, что означает, что [[ 12 > 2 ]] ложно, потому что 1 сортируется раньше 2. Чтобы выполнить числовое сравнение, вам нужно ((...)) вместо [[...]].

Mark Reed 28.10.2022 19:30

Спасибо за ваши предложения. Идея состоит в том, чтобы проверить, содержит ли файл «текст» в «n» последовательных строках, где text и n являются параметрами.

ansanes 28.10.2022 19:39

Это не делает то, о чем просил ОП, I'd like to have an exit value 0 for match and 1 for not match, поэтому я удивлен, что это принятый ответ.

Ed Morton 29.10.2022 20:02

@ansanes Что касается вашего комментария - не делайте этого, так как это запутанно и хрупко по сравнению, например, с одной командой awk. Задайте новый вопрос, чтобы получить помощь, так как этот вопрос не был хорошей отправной точкой для того, что вы действительно пытаетесь сделать.

Ed Morton 29.10.2022 20:04

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

$ awk -v s = "word" '{    # search word as a parameter
    if ($3==p&&$3==s)    # if third word is the same as from previous round
        exit ec=1       # and the same as the search word, exit right away
    else 
        p=$3            # else just store the last word for next round
}
END {                   # in the end
    exit !ec            # flip the error code and exit
}' file

Попробуй это:

$ awk -v s=error '{if ($3==p&&$3==s)exit ec=1;else p=$3}END{exit !ec}' matching
$ echo $?
1
$ awk -v s=error '{if ($3==p&&$3==s)exit ec=1;else p=$3}END{exit !ec}' nonmatching
$ echo $?
0

В приведенном выше примере данных учитываются только третьи слова (или поля, разделенные пробелами). Если вы ищете строку длиннее слова, рассмотрите возможность замены $3 на substr($0,n), где n==18 в вашем образце (начальная точка строки после части даты и времени):

$ awk -v s=error '{
    if (substr($0,18)==p&&substr($0,18)==s)
        exit ec=1
    else 
        p=substr($0,18)
}
END {
    exit !ec
}' file

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