Как можно извлечь одну строку данных из файла и другого процесса в каждой этой строке?

у меня есть файл журнала с содержимым внутри. то есть имя файла convert.20231010.log. Содержимое внутри файла, как показано ниже.

2024-05-17 00:14:02.447 Success ABCXYZ15 on hard disk
2024-05-17 00:14:02.447 Fail at /home/category1/sub1/ABCXYZ01 00054 is not found
2024-05-17 00:14:02.447 Success ABCXYZ16 00030 on hard disk
2024-05-17 00:14:02.447 Fail at /home/category1/sub2/ABCXYZ02 is not found
2024-05-17 00:14:02.447 Success ABCXYZ17 000110 on hard disk

Я хочу проверить файл и поработать над этим.

а) найти в журнале строку с условием «Сбой» и «не найден», получить путь и имя файла.

grep -E 'Fail.*is not found' convert.20231010.log

нашел 2 строки с правильным состоянием

2024-05-17 00:14:02.447 Fail at /home/category1/sub1/ABCXYZ01 00054 is not found
2024-05-17 00:14:02.447 Fail at /home/category1/sub2/ABCXYZ02 is not found

б) выберите файл по пути и проверьте содержимое файла

путь и имя файла будут выбраны из категории 2 на основе основания на шаге a.

/home/category2/sub1/ABCXYZ01 00054
/home/category2/sub2/ABCXYZ02

в) переместить файл, если содержимое хорошее

На основе шага b прочитайте файлы содержимого «ABCXYZ01 00054» и «ABCXYZ02». Если содержание хорошее, переместите файл в категорию3. Проверка содержимого внутри файла — «CARD», если она действительно имеет значение, то файл в порядке. Если «CARD» пусто или пусто, не перемещайте этот файл.

ID=ABCXYZ01 00054
NAME=JOIN
DEPT=ACC
CARD=1234
LOC=NY

ID=ABCXYZ02
NAME=CINDY
DEPT=LOG
CARD=6789
LOC=LA

mv -f '/home/category2/sub1/ABCXYZ01 00054' '/home/category3/sub1/'
mv -f '/home/category2/sub2/ABCXYZ02' '/home/category3/sub2/'

г) удалить строку в файле журнала

этот удалит 2 строки в файле журнала на шаге a

sed -i '/Fail.*is not found/d' convert.20231010.log

Как я могу использовать оболочку bash в Linux и записать новый журнал от шага от a до d? Я не знаком с оболочкой, благодарен за вашу помощь.

#!/bin/bash
MYSELF=$0
MYNAME=`echo $0 | gawk '{print substr($0, match($0, /[^/]+$/))}'`
MYNAME_NOEXT=`echo "$MYNAME" | gawk '{print gensub(/\.[^\.]*$/, "", "g")}'`
MYPATH=`echo $0 | gawk '{print substr($0, 1, match($0, /[^/]+$/) - 1)}'`
if [ $MYPATH == "./" ]; then MYPATH = "`pwd`/"; fi
cd $MYPATH

logfile = "/home/category4/logs/"$MYNAME_NOEXT.`date +"%Y%m%d"`.log

(
if [ `ps -ef | grep -i "$MYNAME" | wc -l` -gt 4 ]
then 
    echo $(date +%Y-%m-%d) $(date +%H:%M:%S)" - Script '$MYNAME' is running. Force exit as re-entry not allowed."
    exit
fi

filename = "convert".`date +"%Y%m%d"`.log
while read -r line; do
    linetext = "$line"
    echo "single line in log - $linetext"
done 

echo $(date) " - Script '$MYNAME' is ended normally."
) >> $logfile 2>&1

Пожалуйста, задавайте только один вопрос в каждом посте. Каждая ваша проблема индивидуально освещается существующими вопросами; пожалуйста, поищите, прежде чем спрашивать. Кроме того, в вашем сценарии есть ряд стилистических проблем; попробуйте shellcheck.net и посмотрите также Правильная заглавная буква переменных Bash и сценария оболочки

tripleee 17.05.2024 11:32

Итак, я сказал, что не знаком с оболочкой, поэтому и спрашиваю. Если не можете, пожалуйста, исключите это. Большое спасибо.

Headshot 17.05.2024 11:42

Прекратите использовать обратные кавычки. Используйте синтаксис $() для замены команд.

William Pursell 17.05.2024 14:27
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать 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
3
66
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Непроверено, поскольку у меня нет и я не хочу создавать структуру каталогов, которая потребуется вашему сценарию и входному файлу для тестирования:

Использование GNU awk для не-POSIX расширений третьего аргумента для match() плюс nextfile, поскольку ОП теперь сообщил нам, что их файл журнала огромен:

#!/usr/bin/env bash

while IFS= read -r file; do
    [[ -f "$file" ]] &&
    >&2 echo mv -f -- "$file" '/home/category3/sub1/'
done < <(
    awk '
        NR == FNR {
            if ( match($0,/Fail at (.*) is not found/,a) ) {
                ARGV[ARGC++] = a[1]
            }
            else {
                print > "newlog.txt"
            }
            next
        }
        /^CARD=[0-9]/ {
            print FILENAME
            nextfile
        }
    ' convert.20231010.log
)

Если у вас нет GNU awk, сделайте это вместо этого с любым awk, который будет работать немного медленнее, если ваш awk не поддерживает nextfile (немногие другие awk поддерживают третий аргумент для match(), но многие поддерживают nextfile и оператор nextfile подойдет). ничего, если не поддерживается, поэтому это безвредно):

#!/usr/bin/env bash

while IFS= read -r file; do
    [[ -f "$file" ]] &&
    >&2 echo mv -f -- "$file" '/home/category3/sub1/'
done < <(
    awk '
        BEGIN {
            beg = "Fail at "
            end = " is not found"
            begLgth = length(beg)
            allLgth = length(beg end)
        }
        NR == FNR {
            if ( match($0,beg ".*" end) ) {
                ARGV[ARGC++] = substr($0,RSTART+begLgth,RLENGTH-allLgth)
            }
            else {
                print > "newlog.txt"
            }
            next
        }
        /^CARD=[0-9]/ {
            print FILENAME
            nextfile
        }
    ' convert.20231010.log
)

[[ -f "$file" ]] && в цикле оболочки защищает нас от любых проблем, если одно и то же имя файла появляется во входных данных несколько раз или /^CARD=[0-9]/ совпадает несколько раз в одном файле, а ваш awk не поддерживает nextfile, и поэтому мы, возможно, уже переместили его на этом этапе. точка в цикле оболочки.

Оригинальный ответ:

$ cat tst.sh
#!/usr/bin/env bash

regexp='Fail at (.*) is not found'
while IFS= read -r line; do
    file = ""
    [[ $line =~ $regexp ]] && file = "${BASH_REMATCH[1]}"
    if [[ -f "$file" ]] && ! grep -q '^CARD=[0-9]' "$file"; then
        >&2 echo mv -f -- "$file" '/home/category3/sub1/'
    else
        printf '%s\n' "$line"
    fi
done < convert.20231010.log > newlog.txt

Удалите >&2 echo, когда закончите тестирование и убедитесь, что скрипт сделает то, что вы хотите.

Другой (возможно, крайне неудобный) метод тестирования — добавить -i к вызову mv.

William Pursell 17.05.2024 14:37

Привет @Эд Мортон, что это за фраза [[ $line =~ $regexp ]] && file = "${BASH_REMATCH[1]}"

Headshot 20.05.2024 11:25

проверяет, соответствует ли содержимое переменной line, например. 2024-05-17 00:14:02.447 Fail at /home/category1/sub1/ABCXYZ01 00054 is not found, сопоставьте содержимое переменных regexp, Fail at (.*) is not found и, если да, установите file в любую часть line, совпадающую с .* в скобках в regexp, т. е. /home/category1/sub1/ABCXYZ01. Это похоже на file=$(printf '%s\n' "$line" | sed -n 's/.*Fail at \(.*\) is not found.*/\1/p'), но со встроенными функциями bash вместо внешних команд и дополнительных процессов.

Ed Morton 20.05.2024 12:34

Ладно, я понял. Кстати, мой журнал очень огромный, в нем ~ 1 миллион строк. Пока не могу использовать while IFS= read -r line; do ....done, очень медленно, если размер файлов очень большой, а количество строк в файле очень велико. Каким-то образом можно сначала использовать grep ""Fail at (.*) is not found, это очень быстро, и можно найти 2 строки с правильным условием. После этого продолжайте обрабатывать только эти две строки. @ЭдМортон

Headshot 21.05.2024 11:12

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

Ed Morton 21.05.2024 12:30

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

Непоследовательные результаты журнала git при фильтрации по каталогу
Цитирование команды оболочки внутри команды osascript, запускаемой оболочкой внутри файла JSON
Как избежать ошибки «Неверный тип аргумента» при выполнении, казалось бы, допустимой команды AWS CLI, созданной с использованием jq и bash?
Как найти одинаковые файлы в дереве каталогов
Используйте вывод сценария с кавычками в качестве аргументов командной строки
Microchip MPLAB X IDE: настройка и запуск общего сценария Bash перед сборкой, который работает как в Windows, так и в Linux как часть процесса сборки
Как получить вывод Telnet в переменную?
Как создать одно и то же расширение PHP для нескольких версий на одном сервере с Ubuntu?
Сортировка пользовательского массива со строками дает неправильный порядок, даже если содержимое файла полностью доступно на диске
Потоковая передача вывода команды bash в cURL