Как использовать grep, чтобы проверить, существует ли строка шаблона, и записать ее в другой файл?

У меня есть файл журнала с таким содержимым

The color is Orange then can used to binding.
The color is Black then can used to binding.
The animal Lion need to carefully. 
The color is Black then can used to binding.
The animal Zebra need to carefully. 
The animal Tiger need to carefully.
The animal Bee need to skip.
The color is White then can used to binding.
The color is Yellow then can used to binding.
The animal Ant need to skip.
The animal Tiger need to carefully. 
The color is Red then can used to filled.
The color is Green then can used to filled.

Я хочу проверить, содержит ли строка шаблон и не существует ли она, а затем записать в другой журнал.

#!/bin/bash
source_file = "/home/user1/source/source_sample.log"
dest_file = "/home/user1/dest/dest_sample.log

#define line with pattern
pattern1 = ".*then can used to binding"
pattern2 = ".*need to carefully"

#check if line of pattern exist or not in destination file, if not then write it
grep -e "$pattern1" -e "$pattern2" $source_file >> $dest_file

Ожидаемый результат в dest_sample.log будет таким. Если строка шаблона не существует в файле назначения, запишите ее. Если он уже существует, не пишите его.

The color is Orange then can used to binding.
The color is Black then can used to binding.
The animal Lion need to carefully. 
The animal Zebra need to carefully. 
The animal Tiger need to carefully.
The color is White then can used to binding.
The color is Yellow then can used to binding.

Если вас не волнует порядок, вы можете просто вставить все совпадающие строки, включая дубликаты, а затем sort | uniq файл назначения.

Verpous 21.08.2024 14:29

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

Brian Crist 21.08.2024 14:51

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

Verpous 21.08.2024 14:58

порядок/последовательность не влияет, строка требования содержит шаблон и не существует в целевом файле журнала. Если файл журнала назначения уже есть, не записывайте эту строку. Посмотрите на результат 7 строк из 13 строк

Brian Crist 21.08.2024 15:01

Пока я не поставил отрицательный голос, см. idownvotedbecau.se/unclearquestion — попробуйте Grammarly или ChatGPT, чтобы получить более четкую версию того, что вы пытаетесь спросить. Лучше написанный вопрос даст вам более быстрые и качественные ответы. Удачи!

Paul Hodges 21.08.2024 16:19
Стоит ли изучать 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
5
89
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Простая команда egrep выполнит фильтрацию, sort -u можно использовать для устранения дубликатов в выводе.

$ egrep '(then can used to binding|need to carefully)' input.txt | sort -u
The animal Lion need to carefully.
The animal Tiger need to carefully.
The animal Tiger need to carefully.
The animal Zebra need to carefully.
The color is Black then can used to binding.
The color is Orange then can used to binding.
The color is White then can used to binding.
The color is Yellow then can used to binding.

Строка The animal Tiger need to carefully. уже существует, не пишите ее больше. пожалуйста, посмотрите образец файла и сравните с моим ожидаемым результатом.

Brian Crist 21.08.2024 14:49

@BrianCrist, это потому, что строки разные: в одной есть конечный пробел.

jhnc 21.08.2024 14:54

@jhnc, а как насчет того, что если я запущу скрипт больше времени, в результате потребуется только 7 строк из 13 строк

Brian Crist 21.08.2024 14:59

@BrianCrist да, большинство ответов не заметили этого требования

jhnc 21.08.2024 15:20

awk на помощь!

$ awk '/then can used to binding|need to carefully/ && ($1=$1) && !a[$0]++' file

The color is Orange then can used to binding.
The color is Black then can used to binding.
The animal Lion need to carefully.
The animal Zebra need to carefully.
The animal Tiger need to carefully.
The color is White then can used to binding.
The color is Yellow then can used to binding.

фильтровать только совпадающие строки, нормализовать поля (избавиться от лишних пробелов) и фильтровать только уникальные записи.

awk '!/re/{next} !seen[$0]++ && NR>FNR' old input >new ?
jhnc 21.08.2024 15:18

Если файлы журналов не помещаются в памяти, вас заботит порядок строк и не заботят конечные пробелы:

(
    awk '
        /then can be used to binding|need to carefully/ { 
            sub(/[[:space:]]+$/,"")
            print NR FS $0
        }
    ' source.log | sort -k2 -u ;

    awk '
        /then can be used to binding|need to carefully/ { 
            sub(/[[:space:]]+$/,"")
            print NR FS $0 RS NR FS $0
        }
    ' destination.log
) |
sort -k2 |
uniq -f1 -u |
sort -n |
sed 's/^[0-9]* //' > new.log

cat new.log >> destination.log
  • сначала awk находит в исходном коде строки, соответствующие регулярному выражению, обрезает конечные пробелы и печатает с префиксом по номеру строки; его вывод затем дедуплицируется с помощью sort, игнорируя номера строк (поле 1)
  • второй awk повторяет фильтрацию для пункта назначения, но печатает каждую строку дважды
  • выходные данные обоих awk объединяются и повторно sort
  • затем uniq отбрасывает дубликаты, также игнорируя номера строк
    • поскольку каждая строка, находящаяся в пункте назначения, появляется как минимум дважды, все строки, уже находящиеся в пункте назначения, отбрасываются.
  • третий sort восстанавливает исходный порядок файлов.
  • затем sed удаляет номер строки
  • наконец, любые новые результаты добавляются к месту назначения.

Если файлы журналов небольшие, подход @karafka можно изменить:

awk '
    !/then can be used to binding|need to carefully/ { next }
    { sub(/[[:space:]]+$/,"") }
    !seen[$0]++ && NR>FNR
' destination.log source.log >new.log

cat new.log >>destination.log
  • отфильтровать строки, которые не соответствуют регулярному выражению

  • обрезать конечные пробелы

  • сохранить эту строку, которую видели

  • при первом появлении строки, если она пришла из нового ввода, распечатайте ее

  • добавить новые результаты в пункт назначения

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

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

Во-первых, в ваших данных есть строки, которые выглядят одинаково, но это не так; у некоторых есть пробелы в конце, а у других нет.

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

Вы спрашивали, как это сделать с помощью grep:

grep -Fxvf $dest_file $source_file | # Fixed string search 
  grep -E 'then can used to binding|need to carefully' >> $dest_file

Требуется два прохода.

Сначала выполняется сканирование -Fфиксированной строки -x(точное совпадение) -v(исключение) $source_file с использованием строк $dest_file в качестве -fфайла совпадающих строк. Это дает нам только строки из $source_file НЕ в $dest_file уже.

Направьте это на grep -E 'then can used to binding|need to carefully' (или grep -e "$pattern1" -e "$pattern2"), чтобы выбрать нужные строки из вывода первого grep и добавить к $dest_file.

Если возможно, что в $source_file могут быть повторяющиеся новые строки, вы можете удалить дубликаты перед их добавлением в $dest_file:

grep -Fxvf $dest_file $source_file | # Fixed string search 
  grep -E 'then can used to binding|need to carefully' |
  sort -u >> $dest_file

Это изменит ваш порядок, если только $source_file не имеет порядка, который вы можете воспроизвести, но вы сказали, что порядок не имеет значения.

Лучший способ

То, что вы просили, было способом использования grep, но awk можно сделать это за один процесс, за один проход (каждый файл), без переупорядочения ваших данных.

awk 'NR==FNR{seen[$0]=1;next} 1==seen[$0]{next} 
  /then can used to binding|need to carefully/{seen[$0]=1;print}
' $dest_file $source_file >> $dest_file

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