поиск и раскрашивание строк с помощью awk или другого метода

Чтобы подсчитать точное количество ошибок, которые rmпроизводит:

find "$CDIR" -depth -mtime +7 -exec sh -c '
    for pathname do
        if ! rm -rfv "$pathname"; then
           count=$(( count + 1 ))
        fi
    done
    printf "This batch caused %d errors in rm\n" "$count"' sh {} +

Это выполнит глубокий -первый поиск в $CDIRи его подкаталогах -и удалит любой файл или каталог с отметкой времени модификации более недели назад. Сценарий оболочки в строке -будет вызываться для пакетов найденных путей, и он выполняет итерацию по каждому, пытаясь удалить его с помощью rm. Если удаление не удалось, оно засчитывается. В конце сценария строки -сообщается количество сбоев для этой партии.

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

Вместо этого вы можете удалить только старые файлы , а затем удалить пустые каталоги по отдельности:

find "$CDIR" ! -type d -mtime +7 -exec sh -c '
    for pathname do
        if ! rm -fv "$pathname"; then
           count=$(( count + 1 ))
        fi
    done
    printf "%d files in this batch could not be deleted\n" "$count"' sh {} +

find "$CDIR" -type d -empty -delete

(Это предполагает, что у вас есть реализация find, которая поддерживает -emptyи -delete, и что вы согласны с удалением пустых каталогов, даже если они не были очищены первой командой find)

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


Другой (более простой )подход заключается в простом удалении старых файлов, а затем подсчете количества старых вещей, которые все еще существуют. Это число будет равно количеству раз rmсбоев (, хотя я использую здесь -deleteдля краткости ):

.
find "$CDIR" ! -type d -mtime +7 -delete
find "$CDIR" ! -type d -mtime +7 -exec echo x \; | wc -l

Затем вы также можете очистить пустые каталоги, как описано выше.

2
15.09.2021, 11:28
4 ответа

Всякий раз, когда вы обнаруживаете, что используете $'{...}'вокруг awk-скрипта, вы делаете что-то не так и должны обратиться за помощью. Никогда не делайте этого, так как это никогда не требуется в хорошо -написанном сценарии и делает ваш сценарий уязвимым, поскольку он предлагает оболочке интерпретировать некоторые его части еще до того, как awk их увидит.

Некоторые люди, столкнувшись с проблемой, думают: «Я знаю, я буду использовать регулярные выражения». Теперь у них две проблемы.:-)

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

awk 'index($0,"DEBUG StateMachine|entr \047NTP:nextGetTimeTimeoutState\047") {
    $0 = "\033[1;41m" $0 "\033[0m"
}
1' LOG.log

\047вместо ', потому что вы не можете экранировать 'в строке с разделителями'-(, включая скрипты )в оболочке. См. http://awk.freeshell.org/PrintASingleQuote.

Чтобы выделить 2 разные линии одним цветом, вы можете использовать:

awk '
    index($0,"DEBUG StateMachine|entr \047NTP:nextGetTimeTimeoutState\047") ||
    index($0,"DEBUG StateMachine|exit \047NTP:nextGetTimeTimeoutState\047") {
        $0 = "\033[1;41m" $0 "\033[0m"
    }
1' LOG.log

и выделить 2 строки двумя разными цветами:

awk '
    index($0,"DEBUG StateMachine|entr \047NTP:nextGetTimeTimeoutState\047") {
        $0 = "\033[1;42m" $0 "\033[0m"
    }
    index($0,"DEBUG StateMachine|exit \047NTP:nextGetTimeTimeoutState\047") {
        $0 = "\033[1;41m" $0 "\033[0m"
    }
1' LOG.log

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

$ cat tst.awk
BEGIN {
    red    = "\033[1;41m"
    green  = "\033[1;42m"
    yellow = "\033[1;43m"
    blue   = "\033[1;44m"
    purple = "\033[1;45m"
    reset  = "\033[0m"

    map["nextGetTimeTimeoutState","entr"] = green
    map["nextGetTimeTimeoutState","exit"] = red
    map["nextIteratorState","entr"]       = yellow
    map["nextIteratorState","task"]       = blue
    map["nextIteratorState","exit"]       = purple
}
match($0,/(DEBUG|INFO) StateMachine\|(\S+)\s+\047NTP:([^\047]+)\047/,a) {
    key = a[3] SUBSEP a[2]
    if ( key in map ) {
        $0 = map[key] $0 reset
    }
}
{ print }

или используя любой POSIX awk:

$ cat tst.awk
BEGIN {
    red    = "\033[1;41m"
    green  = "\033[1;42m"
    yellow = "\033[1;43m"
    blue   = "\033[1;44m"
    purple = "\033[1;45m"
    reset  = "\033[0m"

    map["nextGetTimeTimeoutState","entr"] = green
    map["nextGetTimeTimeoutState","exit"] = red
    map["nextIteratorState","entr"]       = yellow
    map["nextIteratorState","task"]       = blue
    map["nextIteratorState","exit"]       = purple
}
match($0,/(DEBUG|INFO) StateMachine\|[^[:space:]]+[[:space:]]+\047NTP:[^\047]+\047/) {
    split($0,a,/[|[:space:]:\047]+/)
    key = a[9] SUBSEP a[7]
    if ( key in map ) {
        $0 = map[key] $0 reset
    }
}
{ print }

Какой бы из них вы ни использовали, вывод будет:

enter image description here

Вам не нужны промежуточные переменные red, greenи т. д., как можно было бы просто:

    map["nextGetTimeTimeoutState"]["entr"] = "\033[1;42m"
    map["nextGetTimeTimeoutState"]["exit"] = "\033[1;41m"

, но я считаю, что они помогают ясности и упрощают дальнейшее обслуживание/обновления.

9
15.09.2021, 12:28

Если я вас правильно понял, вы можете использовать регулярное выражение и восьмеричное представление одинарных кавычек(\047)вот так:

awk '{ sub(/^.*DEBUG StateMachine\|entr \047NTP:nextGetTimeTimeoutState\047/, "\033[1;41m&\033[0m/); print }' LOG.log

enter image description here

3
15.09.2021, 12:24

Что касается других методов , существуют такие пакеты, как colorizeилиccze

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

Сначала попробуйте значения по умолчанию и посмотрите, понравится ли вам это.

0
15.09.2021, 23:06

Так как это прямолинейное «внесение правок в несколько совпадающих строк», вам не нужны возможности awk. Как уже отмечали другие, большая часть вашей проблемы заключается в правильном цитировании.

Использование sed в одной строке

sed "/DEBUG StateMachine|entr 'NTP:nextGetTimeTimeoutState'/s/.*/"$'\e[[1;41m&\e[0m'/

или в 3

PAT=" DEBUG StateMachine|entr 'NTP:nextGetTimeTimeoutState'"
TO=$'\e[[1;41m&\e[0m'
sed "/$PAT/s/.*/$TO/"
3
16.09.2021, 00:27

Теги

Похожие вопросы