Ich muss Einträge aus einer Protokolldatei extrahieren und in eine Fehlerdatei einfügen.
Ich möchte die Einträge in der Fehlerdatei nicht jedes Mal, wenn das Skript ausgeführt wird, duplizieren. Deshalb erstelle ich Folgendes:
grep $1 $2 | while read -r line ; do
echo "$line"
if [ ! -z "$line" ]
then
echo "Line is NOT empty"
if grep -q "$line" $3; then
echo "Line NOT added"
else
echo $line >> $3
echo "Line added"
fi
fi
done
Und läuft mit:
./log_monitor.sh ERROR logfile.log errors.txt
Bei der ersten Ausführung des Skripts werden die Einträge gefunden und die Fehlerdatei erstellt (vorher keine Fehlerdatei).
Beim nächsten Mal hat diese Zeile die zuletzt hinzugefügten Zeilen zur Fehlerdatei nicht gefunden.
wenn grep -q "$ line" $ 3;
Das Skript fügt daher der Fehlerdatei die gleichen Einträge hinzu.
Irgendwelche Ideen, warum dies geschieht?
Antworten:
3 für die Antwort № 1Dies geschieht höchstwahrscheinlich, weil Sie nicht nach der Zeile selbst suchen, sondern sie als Regex behandeln. Angenommen, Sie haben diese Datei:
$ cat file
[ERROR] This is a test
O This is a test
und Sie versuchen, die erste Zeile zu finden:
$ grep "[ERROR] This is a test" file
O This is a test
Wie Sie sehen, stimmt es nicht mit der Zeile überein, nach der wir suchen (wodurch Duplikate entstehen) und stimmt mit einer anderen Zeile überein (wodurch Einträge gelöscht werden). Sie können stattdessen verwenden -F -x
So suchen Sie nach Literalzeichenfolgen, die der ganzen Zeile entsprechen:
$ grep -F -x "[ERROR] This is a test" file
[ERROR] This is a test
Wenden Sie dies auf Ihr Skript an:
grep $1 $2 | while read -r line ; do
echo "$line"
if [ ! -z "$line" ]
then
echo "Line is NOT empty"
if grep -F -x -q "$line" $3; then
echo "Line NOT added"
else
echo $line >> $3
echo "Line added"
fi
fi
done
Und hier mit zusätzlichen Korrekturen und Bereinigung:
grep -e "$1" -- "$2" | while IFS= read -r line ; do
printf "%sn" "$line"
if [ "$line" ]
then
echo "Line is NOT empty"
if grep -Fxq -e "$line" -- "$3"; then
echo "Line NOT added"
else
printf "%sn" "$line" >> "$3"
echo "Line added"
fi
fi
done
PS: Dies könnte kürzer, schneller sein und eine bessere Komplexität der Zeit mit einem Ausschnitt aus awk
.
0 für die Antwort № 2
Es ist nicht notwendig, nach leeren Zeilen zu suchen; die erste grep
prüft nur Zeilen mit dem Wort "ERROR", die nicht leer sein darf.
Wenn Sie auf die Diagnose verzichten können echo
Nachrichten, so ziemlich der gesamte Code verkürzt, was man mit zwei tun könnte grep
s, a bash
Prozesssubstitution, sponge
, und touch
für den ersten Fall:
[ ! -f $3 ] && touch $3 ; grep -vf $3 <(grep $1 $2) | sponge -a $3