Shell-Skript zum Suchen von Zeichenfolgen in der Protokolldatei

Shell-Skript zum Suchen von Zeichenfolgen in der Protokolldatei

Ich habe ein Skript, das eine Zeichenfolge in einem Verzeichnis aus einer Reihe von Protokolldateien wie folgt abgleicht:

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

Dies gibt eine Liste von Protokolldateien aus, die die gesuchte Zeichenfolge enthalten. Beispiel:

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

Ich möchte diese Ausgabe als Liste wie:

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

Und es wird nach der Nummer 1/2/3/4/5/6 gefragt, um die nummerierte Datei zu öffnen, d. h. wenn ich 4 drücke, wird der Befehl gesendet

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

und die Zeichenfolge „2001NM-100313“ wird in der gesamten Datei gesucht.

Mein Ziel besteht darin, die ganze/n Zeile/n (es kann mehrere Zeilen mit der Zeichenfolge geben) aus den Protokolldateien zu lesen, die diese Zeichenfolge enthalten. Es kann mehrere Protokolldateien mit dieser Zeichenfolge und mehreren Daten geben. Ich muss eine beliebige datierte Datei auswählen und das Protokoll lesen.

Antwort1

Verwenden Sie einfach select(das bashintegrierte).

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

Der gewünschte Code lautet also wahrscheinlich:

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

Beachten Sie, dass dies nicht funktioniert, wenn Ihre Dateinamen Leerzeichen enthalten. Siehe auch:


Wenn Sie jedoch das selectintegrierte Element direkt von aufrufen find, können Leerzeichen problemlos verarbeitet werden.das folgende ist eigentlich besserin allen Fällen, die mir einfallen:

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

Antwort2

Als ich Ihre Frage las, wurde mir wieder bewusst, dass ich mir schon immer ein einfaches Skript gewünscht habe, mit dem ich Dateien einfacher nach einer bestimmten Zeichenfolge durchsuchen und dann eine der Dateien anzeigen kann, die diese Zeichenfolge enthalten. Aufbauend auf Ihrem Skript und dem Vorschlag von Saga, ein Array zu verwenden, habe ich mein eigenes Skript erstellt und auch Ihres fertiggestellt. :)

Bitte beachten: Dieses Skript ist /bin/bash, nicht /bin/sh, weil ich nicht weiß, wie ich das Array in /bin/sh zum Laufen bekomme …

Ihr Skript:

#!/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: Während das obige Skript für die ursprüngliche Frage einwandfrei funktioniert, habe ich auf Wildcards Antwort aufgebaut, so dass mein Skript Dateien mit leeren Leerzeichen verarbeiten kann und verschiedeneWerkzeuge, um die ausgewählte Datei zu öffnen.

Mein Skript:

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

verwandte Informationen