Strings vergleichen und ersetzen

C

calomatic

Mitglied
Hallo!

ich komme bei meinem Problem irgendwie nicht weiter. Ich habe zwei Log Dateien, in der ersten stehen logs mit einer falschen IP (die mir bekannt ist und immer gleich ist) und dahinter ein String, der in der zweiten Datei auch steht mit richtiger vorangestellter IP. Nun möchte ich die falsche IP mit der richtigen ersetzen.

zur Veranschaulichung:
Datei1:
(...)
[irgendeine IP] -- Datum : Uhrzeit angeforderte Datei 20 226
[falsche IP] - - Datum : Uhrzeit angeforderte Datei 304 0
[irgendeine IP] -- Datum : Uhrzeit angeforderte Datei 200 1656
(...)

Datei2:
(...)
[irgendeine IP] -- Datum : Uhrzeit angeforderte Datei 15 436
[richtige IP] -- Datum : Uhrzeit angeforderte Datei 304 0
(...)

an dem String dahinter kann ich die IP's dann genau zuordnen. Der Ablauf wie ich es machen muss ist mir eigentlich klar, mir fehlt nur das nötige know-how. :(

Code:
#Ich habe erstmal die Zeile mit dem ersten Vorkommen der bekannten falschen 
IP rausgesucht:

grep $serverip $datei1 | head -n1 > ip_string_datei1

#Die falsche IP abgeschnitten:

string_datei1=`sed s/$serverip// ip_string_datei1`

#wenn ich dann in der Datei2 nach dem String suchen will um die Zeile mit 
der richtigen IP zu finden passiert nichts. Das Skript hält an ohne Meldung.

grep $string_datei1 $datei2 > zeile_mit_richtiger_ip

Vielleicht kann mir ja jemand von Euch helfen?

MfG Sascha
 
Moin moin,

wenn du dein Script startest, schau dannach doch mal in die variablen was da steht. Dann solltest du das Problem eigentlich sehen.

Gruß Snowman
 
Danke für die schnelle Antwort!

Ich habe jetzt herausgefunden, dass grep nicht mit dem String klar kommt, den er in Datei2 suche soll, weil der so doof formatiert ist:

Code:
Inhalt von $string_datei1:
- - [22/Mar/2006:05:51:39 +0100] "GET /robots.txt HTTP/1.0" 404 285

grep $string_datei1 $datei2 > zeile_mit_richtiger_ip

Ich denk mal es liegt an den Gänsefüsschen ("GET /robots.txt HTTP/1.0"). Gibt es eine Möglichkeit alles was zwischen den Gänsefüsschen, incl. der Gänsefüsschen, zu löschen?

Hab es mit sed noch nicht hinbekommen.

MfG Sascha
 
cut oder bei grep die Option -o kann man verwenden.
 
Hm, ich bekomme es nich nicht hin. ?(

Die Gänsefüsschen bereiten mir Probleme, und mit grep -o 'text' zeigt er mir doch nur den 'text' aus der Zeile an und löscht ihn nicht. :(
 
Hallo
Es ist immer eine gute Idee bei grep den Suchstring zu quoten.
grep "$Suchvariable" inputfile


Code:
#Das erste Vorkommen von $serverip finden und ersetzen geht direkt mit sed:
string_datei1="$(sed -ne "/$serverip/{s/$b//;p;q}" $datei1)"
#Hier einfach quoten:
grep "$string_datei1" $datei2 > zeile_mit_richtiger_ip
...

Gruß Wolfgang
PS Darf man erfahren worin der Sinn liegt, ein Server-Logfile zu manipulieren?
 
Hallo Wolfgang!

Dein Tip mit sed hat mir schonmal weitergeholfen.

Nur leider kann ich den Eintrag immernoch nicht korrekt finden, da grep nun den Suchstring in '...' packt und er nichts als Rückgabewert angibt. Komisch. Wenn ich nach dem string manuell suche finde ich ihn (also er ist auch vorhanden ;)). Packe ich ihn wie grep in '...' dann finde ich ihn nicht.

Hab in meinem Skript #!/bin/sh +x, und da sehe ich, dass grep vollgendes sucht: grep '- - [datum] "GET datei" 405 285' $datei2. Schade.

Ja klar kann man fragen warum ich die Log Dateien manipulieren will. Wir haben ein Webprojekt, bei dem alle Anfragen für https an http weitergeleitet werden. Dadurch stehen in der http Log Datei Einträge von Anfragen des eigenen Servers, da der die Anfragen weiterleitet. Wir haben einen 'Webalizer' der die Log Dateien auswertet und Zugriffe auflistet, da kamen dann auch die Zugriffe mit der eigenen IP zum Vorschein. Nun müssen diese Einträge mit den richtigen IPs korrigiert werden.

Komplizierte Sache wie ich finde. :)
 
Hallo
Entweder du nimmst fgrep und schreibst den gesuchten String in eine Datei, oder du verwendest sed um die " zu escapen.
Dann sollte das gehen.
var2="$(echo $var1|sed -e 's/["]/\"/' )"

Alternativ geht das auch mit einem Perlscript.
Datei1 in ein Array einlesen.
Datei2 einlesen und prüfen ob die Zeile ohne ip im Array vorkommt.
Wenn ja Ip ersetzen.
Am Ende alles augeben.

Gruß Wolfgang
 
calomatic schrieb:
#!/bin/sh +x, und da sehe ich, dass grep vollgendes sucht: grep '- - [datum] "GET datei" 405 285' $datei2.
Ich habe es jetzt nicht getestet...aber könnte es nicht sein, dass das "-" das Problem ist? Man dem grep also das Ende der Argumentliste mitteilen sollte?
In etwa so:
Code:
grep -- '- - [datum] "GET datei" 405 285' $datei2
oder läuft er garnicht erst in das Problem? :think:
 
Schlaubi_fi.de schrieb:
Ich habe es jetzt nicht getestet...aber könnte es nicht sein, dass das "-" das Problem ist? Man dem grep also das Ende der Argumentliste mitteilen sollte?
In etwa so:
Code:
grep -- '- - [datum] "GET datei" 405 285' $datei2
oder läuft er garnicht erst in das Problem? :think:

Nein, das dürfte nicht das Problem sein, wenn es gequotet wird.
Eher geht es hier darum, wenn das mit einfachem Hochkomma -> '$FOO_BAR' gequotet wird, dass dann die darin enthaltenen doppelten Hochkomma zwar bestehen bleiben, jedoch die Variable nicht expandiert.
Bei doppelten "$FOO_BAR" expandiert zwar die Variable, die darin enthaltenen Hochkommata werden jedoch nicht geschützt und beenden so den Suchstring vorzeitig. Was danach kommt, wird als Eingabe gewertet.

Abhilfe dazu habe ich oben vorgeschlagen.

Gruß Wolfgang
 
Hallo!

Danke für die vielen und schnellen Hilfen .. nur leider funktioniert es immernoch nicht. Er kann den string einfach nicht finden. Bekomme immer eine leere Variable zum Schluss.

Ich habe nochmal weiter rumprobiert und ich glaube die eckigen Klammern könnten auch ein Problem sein. Das Datum steht in eckigen Klammern, suche ich nach dem Datum ohne die eckigen Klammern dann habe ich ein eindeutiges Ergebnis, mit eckigen Klammern listet er mir alle Einträge aus der Log Datei. Deshalb habe ich sie auch mal wie die " entwertet.

Code:
serverip='11.11.11.11'

string1="$(sed -ne "/$serverip/{s/$b//;p;q}" $httplog)" 
string2="$(echo $string1|sed -e 's/["]/\"/')"
string3="$(echo $string2|sed -e 's/[[]/\[/')"
string4="$(echo $string3|sed -e 's/[]]/\]/')"
string_mit_ip=`grep -- "$string4" $httpslog` # ohne -- bekomme ich invalid option
# ++string_mit_ip=

# zum Probieren vlt. für Euch:
# inhalt httplog: 
# 11.11.11.11 - - [22/Mar/2006:05:51:39 +0100] "GET /robots.txt HTTP/1.0" 404 285
# inhalt httpslog:
# 22.22.22.22 - - [22/Mar/2006:05:51:39 +0100] "GET /robots.txt HTTP/1.0" 404 285

Ich werde es morgen dann mal mit Perl probieren. Vielleicht klappt es ja dann .. wenn ich den code dafür rausgefunden habe. :)

MfG Sascha
 
Hallo

Ersetze mal das
string1="$(sed -ne "/$serverip/{s/$b//;p;q}" $httplog)"
durch
string1="$(sed -ne "/$serverip/{s/$serverip//;p;q}" $httplog)"


Sorry, bei mir hieß die Testvariable $b statt $serverip, habe ich beim Einkopieren übersehen mit zu ersetzen.

Und gib mal bitte an was
echo $string4
ausgibt.
Gruß Wolfgang
 
Hallo Wolfgang,

stimmt, das $b ist mir garnicht aufgefallen, bzw. ich habe dir da blind vertraut ;) .. das löschen der IP hat ja auch mit der leeren bzw. falschen Variable bei mir geklappt. Hab es nun geändert.

Code:
echo $string4=- - [22/Mar/2006:05:51:39 +0100] "GET /robots.txt HTTP/1.0" 404 285

edit: ah .. gut das du nach echo $string4 gefragt hast. Hab gerade mal manuell grep -- '- - \[22/Mar/2006:05:51:39 +0100\] \"GET /robots.txt HTTP/1.0\" 404 285' $httpslog eingegeben und dann findet er denn string.

Dann hat die Entwertung von ", [ und ] oben mit sed nicht geklappt. Das muss ich noch hinkriegen und dann kann ich mich dem weiteren Verlauf widmen.

MfG Sascha
 
Zuletzt bearbeitet:
Hallo

Wenn
Code:
$string="- - [22/Mar/2006:05:51:39 +0100] "GET /robots.txt HTTP/1.0" 404" 285
#also das Ergebnis aus dem ersten sed ist:
#dann ist
suchpattern_escapet="$(echo $string| sed -e 's/\([]"[-]\)/\\\1/g')"
echo $suchpattern_escapet

\- \- \[22/Mar/2006:05:51:39 +0100\] \"GET /robots.txt HTTP/1.0\" 404 28

und das sollte sich mit
grep "$suchpattern_escapet" input
verheizen lassen.

Gruß Wolfgang
 
Hallo

vielen Dank, so klappt es! Ich denke mal das im weiteren Verlauf noch ein paar Fragen auftreten werden, ich hoffe ich kann dann nochmal deine Hilfe in Anspruch nehmen Wolfgang?

Danke nochmals für die große Hilfe!
 
Hallo
Wenn es sich nur um eine feststehende IP handelt, könntest du die auch gleich im ersten sed einsetzen.
Allerdings musst du besser die . (Punkte) escapen. Das geht hier nur zufällig auch, da der Punkt ein oder kein Zeichen bedeutet.
also besser so:
$(sed -ne "/127\.0\.0\./{s/127\.0\.0\.0//;p;q}" $httplog)"

vielen Dank, so klappt es! Ich denke mal das im weiteren Verlauf noch ein paar Fragen auftreten werden, ich hoffe ich kann dann nochmal deine Hilfe in Anspruch nehmen Wolfgang?

Danke nochmals für die große Hilfe!
Büdde büdde ;)

Dafür sind wir da.
Wir sind zwar keine Scriptfabrik, aber bei erkannter Eigenbemühungen helfen wir gerne, wenn wir können.-> nobody is perfekt

Gruß Wolfgang
 
Hallo!

Ich habe jetzt Zeit gefunden an dem Skript weiter zu arbeiten, aber nun kommt der nächste Holperstein:

Code:
while read input
    do
    echo $input > helper
    grep "$serverip" helper
	if [ $? = 0 ]; then
	    string1="$(sed -ne "/$serverip/{s/$serverip//;p;q}" helper)"
	    string2="$(echo $string1|sed -e 's/\([]"[-]\)/\\\1/g')"
	    grep "$string2" $httpslog >> temp
	else
	    echo $input >> temp
	fi
    rm helper
done < $httplog

Ich wollte, dass er durch die Datei Zeile für Zeile geht, und in der jeweiligen Zeile prüft, ob die Server IP enthalten ist. Wenn ja soll er diese Zeile bearbeiten, sprich IP abschneiden und in httpslog den entsprechend gleichen Eintrag finden und in Datei temp schreiben. Wird die IP nicht gefunden soll die Zeile auch in temp geschrieben werden.

Ich wollte damit die Reihenfolge der logs beibehalten und nur die Zeilen ändern, wo sich die IP befindet.

Nun ist das Problem, dass er genau einmal die IP ändert, und das bei dem ersten Vorkommen der IP. ?(

MfG Sascha

EDIT: ok, das skript funktioniert soweit! Der Code steht ja schon weiter oben in dem Post. Warum nicht alle strings korrekt ersetzt wurden habe ich nun herausgefunden;

Die strings haben am ende immer ein Zahlenpaar, welche in den 2 Log Dateien nicht immer gleich sind. :\

Ich suche jetzt nach einem Weg nach dem letzten " im string den Rest abzuschneiden. :) Ich glaube das wird eine never-ending-story mit dem Skript. :P
 
Zuletzt bearbeitet:

Ähnliche Themen

ersetzen in einem Rückgabestring eines vorher ausgeführten Programms

Zurück
Oben