Shell Script para encontrar string no arquivo de log

Shell Script para encontrar string no arquivo de log

Eu tenho um script que corresponde a uma string em um diretório do número de arquivos de log conforme abaixo:

#!/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" {} \;

Isso gera uma lista de arquivos de log que contém a string pesquisada. Por exemplo:

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

Eu quero essa saída como uma lista como:

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

E pedirá a entrada do número 1/2/3/4/5/6 que abrirá aquele arquivo numerado, ou seja; se eu pressionar 4 ele enviará o comando

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

e a string "2001NM-100313" será pesquisada em todo o arquivo.

Meu objetivo é ler toda a linha/linhas (pode haver várias linhas com a string) que contêm essa string dos arquivos de log, pode haver vários arquivos de log que possuem essa string com várias datas, preciso selecionar qualquer arquivo datado e leia o registro.

Responder1

Basta usar select(o bashembutido).

$ 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.
$

Então o código que você deseja é provavelmente:

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

Observe que se seus nomes de arquivos contiverem espaços em branco, isso será interrompido. Veja também:


No entanto, se você chamar o selectbuiltin diretamente de find, isso irá lidar com espaços em branco com facilidade. Entãoo seguinte é realmente melhorem todos os casos, posso pensar em:

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 {} +

Responder2

Ler sua pergunta me lembrou de sempre querer ter um script simples que tornasse mais fácil para mim pesquisar arquivos para uma string específica e depois olhar para um dos arquivos que contém a string. Com base no seu script e na sugestão da saga de usar um array, criei meu script e também finalizei o seu. :)

Observação: este script é /bin/bash, não /bin/sh, porque não sei como fazer o array funcionar em /bin/sh...

Seu roteiro:

#!/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

EDIT: Embora o script acima funcione perfeitamente para a pergunta original, desenvolvi a resposta do Wildcard, para que meu script possa lidar com arquivos com espaços vazios e ofereça váriosferramentaspara abrir o arquivo selecionado.

Meu roteiro:

#!/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

informação relacionada