Как передать динамическое число аргументов в sed для использования в качестве фильтров - PullRequest
0 голосов
/ 30 октября 2019

Я бы хотел иметь возможность легко искать файлы журналов.

Мои файлы журналов очень большие и выглядят так. ,.

-------------------------------
id=<id>
request=<request>
...
status=<status>
metrics=<metrics>
-------------------------------
id=<id>
request=<request>
...
status=<status>
metrics=<metrics>

Каждый журнал начинается с строки из тире, а затем для каждого журнала регистрируется несколько строк информации, которые могут измениться.

Так что я хотел бы получить выводлюбых журналов, которые соответствуют динамическому числу фильтров.

Я планирую сделать эту функцию bash, которую я могу вызвать и передать в filename и нескольких фильтрах

Например, вызов ее с помощью одногофильтр

$ searchLogs <filename> <first-match>

например, вызов его с несколькими фильтрами

$ searchLogs <filename> <first-match> <second-match> <third-match> ...

Я нашел команду, которую можно использовать для сопоставления с одним фильтром

$ sed '/^---/ !{H;$ !d};x;/<search_term>/ !d'

.. .и я мог бы создать несколько функций разной длины и просто добавлять ;/<search_term>/ !d к нему для каждого дополнительного поискового запроса, но я бы хотел построить его динамически, если это возможно, и сохранить его в функции, чтобы я мог легко поделиться ею с членами команды.

Вот примерно так я думаю. ,,но мне не повезло

function searchRequestLogs() {
    logFile="$1"
    searchTerms="${@:2}"
    sedString="'"'/^---/ !{H;$ !d};x';

    for searchTerm in $searchTerms
    do
       # append searchTerm
       sedString=$sedString';/'$searchTerm'/ !d';
    done
    sedString=$sedString"'"

    cat $logFile | sed $sedString;
}

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

Ответы [ 2 ]

1 голос
/ 30 октября 2019

Вы можете использовать grep вместо sed для поиска текста:

search_logs() {
    local logfile="$1"
    local searchterms="${@:2}"
    searchterms="${searchterms// /\\|}"
    grep "$searchterms" "$logfile"
}

Пример ввода:

$ cat testfile
a
b
c
d
e

Пример вывода:

$ search_logs testfile a d e
a
d
e

Несколькопримечания:

  • использовать local, чтобы избежать загрязнения глобального пространства имен
  • , использовать подстановку параметров для создания строки поиска. Для приведенного выше примера это a\|d\|e
0 голосов
/ 30 октября 2019

Вот окончательное решение, которое я придумал для sed. Рад за других, чтобы найти возможно лучшие решения. Особенно, если есть какие-либо улучшения скорости, которые могут быть сделаны, так как некоторые файлы журнала могут быть ОЧЕНЬ большими

# Search a log file with an arbitrary number of search filters
function searchRequestLog() {
    local logFile="$1"
    local filters="${@:2}"
    local sedScript='/^---/ !{H;$ !d};x';

    # loop over filters and add each to sed script
    for filter in $filters
    do
       # append filter
       sedScript=$sedScript';/'$filter'/ !d';
    done;

    # search log file for log events that contain ALL filters
    sed -e "$sedScript" "$logFile";
}
...