Скрипт оболочки для поиска строки в файле журнала

Скрипт оболочки для поиска строки в файле журнала

У меня есть скрипт, который сопоставляет строку в каталоге из нескольких файлов журнала, как показано ниже:

#!/bin/sh
# Collect Customer ID as input
read -p "Enter Customer ID: " custid
echo "Searched customer ID $custid found in following logs: "
# Find the customer id as string in specified directory
find /usr/local/tomcat9/logs/ -type f -exec grep -l "$custid" {} \;

Это выводит список файлов журнала, содержащих искомую строку. Например:

Enter Customer ID: 2001NM-100313
Searched customer ID 2001NM-100313 found in following logs:
/usr/local/tomcat9/logs/localhost_access_log.2017-10-04.txt
/usr/local/tomcat9/logs/localhost_access_log.2017-07-11.txt
/usr/local/tomcat9/logs/localhost_access_log.2017-11-02.txt
/usr/local/tomcat9/logs/localhost_access_log.2017-09-11.txt
/usr/local/tomcat9/logs/localhost_access_log.2017-08-09.txt
/usr/local/tomcat9/logs/localhost_access_log.2017-06-11.txt

Я хочу, чтобы этот вывод был в виде списка:

1. /usr/local/tomcat9/logs/localhost_access_log.2017-10-04.txt
2. /usr/local/tomcat9/logs/localhost_access_log.2017-07-11.txt
3. /usr/local/tomcat9/logs/localhost_access_log.2017-11-02.txt
4. /usr/local/tomcat9/logs/localhost_access_log.2017-09-11.txt
5. /usr/local/tomcat9/logs/localhost_access_log.2017-08-09.txt
6. /usr/local/tomcat9/logs/localhost_access_log.2017-06-11.txt

И он попросит ввести число 1/2/3/4/5/6, которое откроет этот пронумерованный файл, т.е. если я нажму 4, он отправит команду

vim /usr/local/tomcat9/logs/localhost_access_log.2017-09-11.txt

и строка «2001NM-100313» будет найдена по всему файлу.

Моя цель — прочитать всю строку/строки (строок со строкой может быть несколько), которые содержат эту строку из файлов журнала. Может быть несколько файлов журнала, которые содержат эту строку с несколькими датами. Мне нужно выбрать любой файл с датой и прочитать журнал.

решение1

Просто используйте select( bashвстроенную функцию).

$ help select
select: select NAME [in WORDS ... ;] do COMMANDS; done
    The WORDS are expanded, generating a list of words.  The
    set of expanded words is printed on the standard error, each
    preceded by a number.  If `in WORDS' is not present, `in "$@"'
    is assumed.  The PS3 prompt is then displayed and a line read
    from the standard input.  If the line consists of the number
    corresponding to one of the displayed words, then NAME is set
    to that word.  If the line is empty, WORDS and the prompt are
    redisplayed.  If EOF is read, the command completes.  Any other
    value read causes NAME to be set to null.  The line read is saved
    in the variable REPLY.  COMMANDS are executed after each selection
    until a break command is executed.
$

Итак, код, который вам нужен, вероятно, следующий:

read -p 'Enter Customer ID: ' custid
select f in $(find /usr/local/tomcat9/logs -type f -exec grep -q -e "$custid" {} \; -print); do
  vim "$f"
done

Обратите внимание, что если имена файлов содержат пробелы, это приведет к сбою. Смотрите также:


Однако если вы вызовете selectвстроенную функцию напрямую из find, она легко справится с пробелами. Так чтоследующее на самом деле лучшево всех случаях, которые приходят мне на ум:

read -p 'Enter customer ID: ' custid
find /usr/local/tomcat9/logs -type f -exec grep -qe "$custid" {} \; -exec bash -c '
  select f; do vim "$f"; done' find-sh {} +

решение2

Прочитав ваш вопрос, я вспомнил, что всегда хотел иметь простой скрипт, который бы упростил мне поиск файлов для определенной строки, а затем просмотр одного из файлов, содержащих эту строку. Основываясь на вашем скрипте и предложении saga использовать массив, я создал свой скрипт и также закончил ваш. :)

Обратите внимание: этот скрипт — /bin/bash, а не /bin/sh, потому что я не знаю, как заставить массив работать в /bin/sh...

Ваш сценарий:

#!/bin/bash
# Collect Customer ID as input
read -p "Enter Customer ID: " custid
echo "Searched customer ID $custid found in following logs: "
# Find the customer id as string in specified directory

arr=( $(find /usr/local/tomcat9/logs/ -type f -exec grep -l "$custid" {} \; | sort -r) )

if [ ${#arr[@]} -eq 0 ]; then
    echo "No matches found."
else
    arr+=('Quit')
    select opt in "${arr[@]}"
    do
        case $opt in
            "Quit")
                break
                ;;
            *)
                vim $opt
                break
                ;;
        esac
    done
fi

ПРАВКА: Хотя приведенный выше скрипт отлично подойдет для исходного вопроса, я основывался на ответе Уайлдкарда, поэтому мой скрипт может обрабатывать файлы с пустыми пространствами и предлагает различныеинструментычтобы открыть выбранный файл.

Мой сценарий:

#!/bin/bash
# Find string in files of given directory (recursively)

read -p "Enter search string: " text
read -p "Enter directory: " directory

#arr=( $(find $directory -type f -exec grep -l "$text" {} \; | sort -r) )
#find $directory -type f -exec grep -qe "$text" {} \; -exec bash -c '

file=$(find $directory -type f -exec grep -qe "$text" {} \; -exec bash -c 'select f; do echo $f; break; done' find-sh {} +;)

if [ -z "$file" ]; then
    echo "No matches found."
else
    echo "select tool:"
    tools=("nano" "less" "vim" "quit")
    select tool in "${tools[@]}"
    do
        case $tool in
            "quit")
                break
                ;;
            *)
                $tool $file
                break
                ;;
        esac
    done
fi

Связанный контент