sed: langen Textblock ersetzen [gelöst]
sed: langen Textblock ersetzen [gelöst]
In einem Script möchte ich einen Textblock ersetzen:
sed 's|alterText|neuerText|g'
Wie lang darf alterText sein, bzw. wie sähe das aus, wenn alterText eine eigene Datei ist? Das was da raus soll ist Javascript-Code, der z.B.Klammern, Semikolon, </script> enthält. Wird sed durch die Sonderzeichen gestört?
sed 's|alterText|neuerText|g'
Wie lang darf alterText sein, bzw. wie sähe das aus, wenn alterText eine eigene Datei ist? Das was da raus soll ist Javascript-Code, der z.B.Klammern, Semikolon, </script> enthält. Wird sed durch die Sonderzeichen gestört?
Zuletzt geändert von Karamel am 23.02.2021 20:21:14, insgesamt 1-mal geändert.
Re: sed: langen Textblock ersetzen
Sed arbeitet zeilenweise, der zu ersetzende Text kann also nur Teil einer Zeile sein. Mehrzeiliger Text kann mit sed so nicht ersetzt werden. (In Perl/Python/PHP/etc. ist das moeglich.)
Wenn der zu ersetzende Text ganze Zeilen umfasst, dann kann man das c-Kommando verwenden (oder `d' in Kombination mit `r'). Das ist aber alles nicht so bequem.
Kannst du dein Problem genauer beschreiben? Vielleicht auch ein Beispiel posten. Vielleicht gibt es ja auch andere Wege.
Wenn der zu ersetzende Text ganze Zeilen umfasst, dann kann man das c-Kommando verwenden (oder `d' in Kombination mit `r'). Das ist aber alles nicht so bequem.
Kannst du dein Problem genauer beschreiben? Vielleicht auch ein Beispiel posten. Vielleicht gibt es ja auch andere Wege.
Use ed once in a while!
Re: sed: langen Textblock ersetzen
Es geht darum, eine Homepage zu reparieren. Da ist bei einem Angriff in sehr viele .php und .js-Dateien derselbe Javascript-(Schad-)Code eingefügt worden - allerdings an unterschiedlichen Stellen in der Datei: mal am Anfang, mal mittendrin. Ich habe vor Jahren mal für einen ähnlichen Zweck sed s benutzt, daher die Idee hier wieder sed zu benutzen.
Re: sed: langen Textblock ersetzen
Muss man den Codeblock loeschen oder ersetzen?
Hat der Textblock denn eine eindeutige Anfangs- und Endzeile? Wenn es die beiden genau einmal in den Dateien gibt und man den Block nur entfernen will, dann kann man das mit sed machen:
(Davor ein Backup anlegen!)
Was bei sed nicht moeglich ist, ist ein Regulaerer Ausdrueck ueber mehrere Zeilen. Aber ein Perl-Programmierer kann dir sicher schnell einen Dreizeiler hinschreiben, der das kann.
Hat der Textblock denn eine eindeutige Anfangs- und Endzeile? Wenn es die beiden genau einmal in den Dateien gibt und man den Block nur entfernen will, dann kann man das mit sed machen:
Code: Alles auswählen
sed -i '/eindeutiger-text-der-startzeile/,/eindeutiger-text-der-endzeile/d' DATEIEN...
Was bei sed nicht moeglich ist, ist ein Regulaerer Ausdrueck ueber mehrere Zeilen. Aber ein Perl-Programmierer kann dir sicher schnell einen Dreizeiler hinschreiben, der das kann.
Use ed once in a while!
Re: sed: langen Textblock ersetzen
Ich hab gerade mal 2 Minuten online gesucht (nach ``replace multiline string in text file'') und allerlei Antworten gefunden, u.a. diese: https://unix.stackexchange.com/question ... g-in-files
Die Essenz ist:
Die Essenz ist:
Code: Alles auswählen
perl -i -p0e 's/Some.*?thing\n/`cat new`/se' input.txt ...
Use ed once in a while!
Re: sed: langen Textblock ersetzen
Zu "cat" fällt mir Useless use of * ein: https://www.socallinuxexpo.org/scale5x/ ... aumann.pdf (ab Seite 20)Meillo hat geschrieben:Code: Alles auswählen
perl -i -p0e 's/Some.*?thing\n/`cat new`/se' input.txt ...
Ich denke man könnte das auch ganz einfach mit "awk" schreiben.
- wenn Start gefunden setze einer Variable
- solange Variable gesetzt Zeile löschen
- wenn Stop gefunden die Variable nicht mehr setzen.
Vielleicht mag es jemand programmieren.
Re: sed: langen Textblock ersetzen
Dazu habe ich auch etwas zu bieten: http://marmaro.de/docs/chaosseminar/on- ... rmance.pdf (ab Seite 5)uname hat geschrieben:09.02.2021 13:40:32Zu "cat" fällt mir Useless use of * ein: https://www.socallinuxexpo.org/scale5x/ ... aumann.pdf (ab Seite 20)Meillo hat geschrieben:Code: Alles auswählen
perl -i -p0e 's/Some.*?thing\n/`cat new`/se' input.txt ...
Ich denke aber, dass es sich hier um einen useful use of cat handelt, oder wie wuerdest du das sonst einfacher machen? Gibt es in Perl ein ``read file and return contents'' als Funktion?
Nur wenn es eindeutige Start- und Endzeilen gibt. Dann geht es auch mit sed. Bislang war die Anforderung jedoch, dass es ein *mehrzeiliger* Suchstring ist ... und das kann weder sed noch awk direkt. Dazu muesste man sich selber etwas bauen. Perl aber kann das (mittels des `s' Parameters nach dem s///).Ich denke man könnte das auch ganz einfach mit "awk" schreiben.
- wenn Start gefunden setze einer Variable
- solange Variable gesetzt Zeile löschen
- wenn Stop gefunden die Variable nicht mehr setzen.
Vielleicht mag es jemand programmieren.
Use ed once in a while!
Re: sed: langen Textblock ersetzen
Meillo hat geschrieben:09.02.2021 15:24:20Nur wenn es eindeutige Start- und Endzeilen gibt. Dann geht es auch mit sed. Bislang war die Anforderung jedoch, dass es ein *mehrzeiliger* Suchstring ist ... und das kann weder sed noch awk direkt. Dazu muesste man sich selber etwas bauen. Perl aber kann das (mittels des `s' Parameters nach dem s///).
Code: Alles auswählen
awk '{print NR " " NF}' datei.txt
Code: Alles auswählen
awk 'BEGIN {RS = EOF}{print NR " " NF}' datei.txt
Und da kommen wir zu dem Punkt, an dem man sich überlegen sollte, ob das ne gute Idee ist.
@Karamel : wenn Du das machst, sei Dir im klaren, dass Du vermutlich an einigen Stellen falsches löscht oder noch weitere Überreste der Scripte hinterblieben sind. Es ist sehr unwahrscheinlich, dass alle Modifikationen so einfach zu erkennen sind.
Re: sed: langen Textblock ersetzen
Richtig! Awk kann es. Da hatte ich einen Knoten im Hirn.eggy hat geschrieben:09.02.2021 19:09:42Meillo hat geschrieben:09.02.2021 15:24:20Nur wenn es eindeutige Start- und Endzeilen gibt. Dann geht es auch mit sed. Bislang war die Anforderung jedoch, dass es ein *mehrzeiliger* Suchstring ist ... und das kann weder sed noch awk direkt. Dazu muesste man sich selber etwas bauen. Perl aber kann das (mittels des `s' Parameters nach dem s///).vsCode: Alles auswählen
awk '{print NR " " NF}' datei.txt
Code: Alles auswählen
awk 'BEGIN {RS = EOF}{print NR " " NF}' datei.txt
Wenn er nicht nur auf irgendwelche *vermutlich* nur einmal vorkommende Marker matcht, sondern den spezifischen Textblock insgesamt ersetzt (wie das mit dem Perl-Befehl moeglich ist), dann ist das deutlich robuster. Es ist dann zwar auch kein String-Search-Replace, sondern ein RE-Matchen-Replace, aber immerhin.Als RS kann man auch nen regex benutzen. Mit anderen Worten, man könnte direkt an "<script" trennen bzw an "<script>" und "</script>" oder diversen Varianten davon.
Und da kommen wir zu dem Punkt, an dem man sich überlegen sollte, ob das ne gute Idee ist.
@Karamel : wenn Du das machst, sei Dir im klaren, dass Du vermutlich an einigen Stellen falsches löscht oder noch weitere Überreste der Scripte hinterblieben sind. Es ist sehr unwahrscheinlich, dass alle Modifikationen so einfach zu erkennen sind.
In den modernen Scriptsprachen sollte das alles kein grosses Problem sein.
... wobei es in diesem Thread ja gerade weniger an den Moeglichkeiten scheitert, als mehr daran, dass Karamel sich nicht mehr meldet.
Use ed once in a while!
Re: sed: langen Textblock ersetzen
In PHP (weil Perl oder Python kann ich nicht) koennte das in etwa so aussehen:
(Ungetesteter Code!)
Letztlich fehlt nur der Input fuer die Liste von Dateien, in denen ersetzt werden soll, ueber die iteriert werden muss ... und alle Fehlerbehandlung. Vom Prinzip waere das ein reiner String-Replace, in dem nichts escapt werden muss oder so.
Btw: Man muss das Paket php7-cli installieren, um PHP fuer Scripte von der Kommandozeile nutzen zu koennen.
Code: Alles auswählen
$file = "foo.html";
$data = file_get_contents($file);
$search = <<<'EOF'
<script>
... beliebige Zeilen ...
</script>
EOF;
$replace = <<<'EOF'
leer oder Ersatzzeilen
EOF;
file_put_contents($file, str_replace($search, $replace, $data));
Letztlich fehlt nur der Input fuer die Liste von Dateien, in denen ersetzt werden soll, ueber die iteriert werden muss ... und alle Fehlerbehandlung. Vom Prinzip waere das ein reiner String-Replace, in dem nichts escapt werden muss oder so.
Btw: Man muss das Paket php7-cli installieren, um PHP fuer Scripte von der Kommandozeile nutzen zu koennen.
Use ed once in a while!
Re: sed: langen Textblock ersetzen
Danke Mello, soweit ich das verstanden habe, werden dann die ganzen Zeilen gelöscht. Allerdings bin ich mir nicht sicher, ob der Schadcode immer am Zeilenanfang anfängt und am Zeilenende endet. Deshalb bin ich zu Plan B übergegangen, d.h. ich versuche den Schadcode scheibchenweise abzutragen. Das funktioniert auch bei den ersten Scheiben, aber hier funktioniert es nicht:Meillo hat geschrieben:08.02.2021 20:05:01Muss man den Codeblock loeschen oder ersetzen?
Hat der Textblock denn eine eindeutige Anfangs- und Endzeile? Wenn es die beiden genau einmal in den Dateien gibt und man den Block nur entfernen will, dann kann man das mit sed machen:
Code: Alles auswählen
sed -i '/eindeutiger-text-der-startzeile/,/eindeutiger-text-der-endzeile/d' DATEIEN...
Code: Alles auswählen
ft4="(String.fromCharCode(115,99,114,105,112,116))[0]);elem.appendAfter(document.getElementsByTagName(String.fromCharCode(104,101,97,100))[0]);"
ft5="document.getElementsByTagName(String.fromCharCode(104,101,97,100))[0].appendChild(elem);})();"
sed "s|$ft4||g" test.php > test.php.tmp && mv test.php.tmp test.php
sed "s|$ft5||g" test.php > test.php.tmp && mv test.php.tmp test.php
Re: sed: langen Textblock ersetzen
Ich habe den Befehl nochmal einfach auf der Kommandozeile eingegeben, aber obwohl ich den Suchtext aus der Test-Datei rauskopiert habe, findet keine Ersetzung (bzw. Löschung) statt.
Re: sed: langen Textblock ersetzen
sed stört sich wohl an den vielen Klammern_auf...
vielleicht gehts mit einem kleinen Umweg (Ersetzung durch Punkt):
vielleicht gehts mit einem kleinen Umweg (Ersetzung durch Punkt):
Code: Alles auswählen
ft41=$(echo ${ft4//[([{]/.})
ft51=$(echo ${ft5//[([{]/.})
sed "s|$ft41||g" test.php > test.php.tmp && mv test.php.tmp test.php
sed "s|$ft51||g" test.php > test.php.tmp && mv test.php.tmp test.php
Gruß an alle Debianer, und immer daran denken:
Macht ohne Haftung funktioniert nicht!
Macht ohne Haftung funktioniert nicht!
Re: sed: langen Textblock ersetzen
Mein Eindruck ist, dass dieser ganze Ansatz mit sed mehr Hindernis als Hilfe ist. Nichts Schlimmeres wie wenn man irgendwann halb oder teilweise ersetzte Daten hat. Mit sed gibt es so viele Stolpersteine, die es zu nehmen gilt.
Ich moechte doch nochmal empfehlen ein Script in Perl/PHP/Python/Ruby/etc. zu verwenden, das in einer Datei (unabhaengig von Zeilen) Textbloecke ersetzen kann. Beispiele fuer solche Umsetzungen habe ich fuer Perl und fuer PHP gepostet. Dann in der Shell ueber alle Dateien iterieren und fuer jede das Script aufrufen. Anschliessend stichprobenhaft pruefen, dass aller unerwuenschter Code ersetzt worden ist.
Selbst wenn du diese Programmiersprachen nicht kannst, denke ich, dass dich dieser Ansatz schneller und v.a. robuster zum Ziel bringt als mit sed rumzuwerkeln. (Wir koennen dich bei deinen Versuchen ja unterstuetzen.) Aber naterlich kannst du es machen wie du es willst, und es gibt hier vielleicht auch andere Meinungen als meine ...
Ich moechte doch nochmal empfehlen ein Script in Perl/PHP/Python/Ruby/etc. zu verwenden, das in einer Datei (unabhaengig von Zeilen) Textbloecke ersetzen kann. Beispiele fuer solche Umsetzungen habe ich fuer Perl und fuer PHP gepostet. Dann in der Shell ueber alle Dateien iterieren und fuer jede das Script aufrufen. Anschliessend stichprobenhaft pruefen, dass aller unerwuenschter Code ersetzt worden ist.
Selbst wenn du diese Programmiersprachen nicht kannst, denke ich, dass dich dieser Ansatz schneller und v.a. robuster zum Ziel bringt als mit sed rumzuwerkeln. (Wir koennen dich bei deinen Versuchen ja unterstuetzen.) Aber naterlich kannst du es machen wie du es willst, und es gibt hier vielleicht auch andere Meinungen als meine ...
Use ed once in a while!
Re: sed: langen Textblock ersetzen
Mello, vielen Dank für das Hilfsangebot, aber ich möchte erst einmal versuchen, das Problem mit den Mitteln zu lösen, die ich halbwegs verstehe, bzw. mit den Mitteln, die ich kurzfristig in der Lage bin dazuzulernen.
detix, das sieht interessant aus, aber ich verstehe nur, dass die Variable ft4 ausgegeben wird, mit der Ausgabe offenbar etwas angestellt wird und das Ergebnis in Variabl2 ft41 gespeichert wird. Was passiert da genau?
detix, das sieht interessant aus, aber ich verstehe nur, dass die Variable ft4 ausgegeben wird, mit der Ausgabe offenbar etwas angestellt wird und das Ergebnis in Variabl2 ft41 gespeichert wird. Was passiert da genau?
Re: sed: langen Textblock ersetzen
Führe es doch einfach aus:
es werden sämtliche öffnende runde, eckige und geschweifte Klammern durch einen Punkt ersetzt, letzterer steht für jedes x-beliebige Zeichen, so kann sed auch den kompletten String finden und ersetzen.
Allerdings wird das so nichts werden, zumindest für $ft5 fehlen dir zugehörige öffnende Klammern und doppelte Anführungszeichen, das zerreißt dir alles!
So einfach wie du denkst wird der Schaden nicht zu reparieren sein.
Code: Alles auswählen
echo $ft5
document.getElementsByTagName(String.fromCharCode(104,101,97,100))[0].appendChild(elem);})();
echo ${ft5//[([{]/.}
document.getElementsByTagName.String.fromCharCode.104,101,97,100)).0].appendChild.elem);}).);
Allerdings wird das so nichts werden, zumindest für $ft5 fehlen dir zugehörige öffnende Klammern und doppelte Anführungszeichen, das zerreißt dir alles!
So einfach wie du denkst wird der Schaden nicht zu reparieren sein.
Gruß an alle Debianer, und immer daran denken:
Macht ohne Haftung funktioniert nicht!
Macht ohne Haftung funktioniert nicht!
Re: sed: langen Textblock ersetzen
So, ich hab's hinbekommen. Gestolpert ist sed über die eckigen Klammern. DIe habe ich aber mit Mellos Zeile mit -i und d auch noch weggetrickst.
Re: sed: langen Textblock ersetzen
Cool.Karamel hat geschrieben:22.02.2021 20:24:58So, ich hab's hinbekommen. Gestolpert ist sed über die eckigen Klammern. DIe habe ich aber mit Mellos Zeile mit -i und d auch noch weggetrickst.
Hast du das Problem damit geloest? Ist aller Stoertext entfernt? (Falls ja, dann ergaenze den Titel im ersten Post doch um ein [gelöst].)
Btw: Meillo.
Use ed once in a while!