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 bash
integrierte).
$ 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 select
integrierte 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