Anmelden

Archiv verlassen und diese Seite im Standarddesign anzeigen : Shell Script soll Einträge in Datei ändern



CaptainAlphabet
07-02-2004, 23:17
Wisst ihr, wie ein Shell Script die Zeilen, die es sich mit "grep" aus einer anderen Datei rausgesucht hat, verändern kann?

fork
07-02-2004, 23:51
Direktes Ändern geht nicht, Nur über eine temporäre Datei mit sed.

sed -e s/alt/neu/ datei.alt >datei.neu
mv -f datei.neu datei.alt

CaptainAlphabet
08-02-2004, 11:58
Danke!
Kannst du mir auch sagen, wie ich eine komplette Zeile ersetzen kann, wenn ich nur dessen Anfang kenne?


Beispiel (unterstrichener Text unbekannt):
[...]
CaptainAlphabet kriegt's nicht hin.
[...]


sed s/CaptainAlphabet/CaptainAlphabet hat's geschafft/ Beispiel.alt > Beispiel.neu
würde nämlich ausgeben:
[...]
CaptainAlphabet hat's geschafftkriegt's nicht hin.
[...]

peschmae
08-02-2004, 12:15
Mit


sed s/CaptainAlphabet/CaptainAlphabet hat's geschafft/ Beispiel.alt > Beispiel.neu

sucht sed nur nach CaptainAlphabet und ersetzt dementsprechend auch nur das. Damit die ganze Zeile gefunden und damit nachher auch ersetzt wird machst du sowas:


sed s/CaptainAlphabet.*/CaptainAlphabet hat's geschafft/ Beispiel.alt > Beispiel.neu

(Sed arbeitet per Default Zeilenweise - wenn du einen Ausdruck auf das ganze Dokument, über Zeilengrenzen hinweg anwenden musst, dann ist ein Spezialparameter an Sed fällig)

Falls nur alle CaptainAlphabet-Zeilen mit CA am Anfang gefunden werden sollen geht das dann mit ^


sed s/^CaptainAlphabet.*/CaptainAlphabet hat's geschafft/ Beispiel.alt > Beispiel.neu


In diesem Beispiel musst du aber aufpassen, weil das ' das eingesetzt wird benutzt wird um eine Zeichenkette zwischen zwei ' vor dem ersetzt werden zu schützten - das läuft dann in dem Fall auf sowas hinaus:


sed s/^CaptainAlphabet.*/"CaptainAlphabet hat"\'"s geschafft"/ Beispiel.alt > Beispiel.neu


Die " sind nötig um die Leerschläge zu schützen (könntest auch jeweils ein \ vor jeden Leerschlag pflanzen) - müssen aber vor dem ', das ja ein normales Zeichen ist aufhören - das muss separat mit einem \ Escaped werden...

Noch n bisschen Lektüre: Klick (http://www.student.northpark.edu/pemente/sed/) und Klick (http://www.grymoire.com/Unix/index.html) .

Und zum Trost: So einfache sachen krieg ich zwar meist einfach so hin - aber schon ein bisschen kompliziertere Sachen muss ich auch nachschlagen.

MfG Peschmä

CaptainAlphabet
08-02-2004, 15:15
Danke!
Ich habe auch versucht mir Wildcards zu arbeiten, aber der Punkt vor dem Stern war mir neu.

peschmae
08-02-2004, 17:03
Sed arbeitet halt mit Regexps. Und dort gilt:

*: Das vorherige Zeichen mindestens 0 mal
+: Das vorherige Zeichen mindestens 1 mal
?: Das vorherige Zeichen 0 oder 1 mal
uvam.

.: irgend ein Zeichen

Das wars schon. :)

MfG Peschmä

sticky bit
08-02-2004, 17:56
Wenn es auch PERL sein darf:
perl -p -i -e 's/^.*schaffts nicht$/Andere Zeile/' datei
würde dann alle Zeilen die mit "schaffsts nicht" enden in "Andere Zeile" ändern.
Für alles weitere gibt man perl bzw. perldoc perl und deren weiterführende Dokumente sowie zahlreiche Webseiten Auskunft...

peschmae
08-02-2004, 18:23
Das ist aber Overhead :eek:

Sed ist bei mir 36KB, Perl 1.1MB gross. Geht natürlich genau so gut :)

MfG Peschmä

kamome
06-08-2004, 13:36
Hi!

Da ich ein aehnliches Problem habe, waerme ich diesen thread mal wieder auf ;)

c-shell, sed.

In einer Schleife sollen einige Dateien editiert werden; diese sind nacheinander in ${file} zu finden.
Ich habe eine Variable ${prefix}, mit der ich Zeilen der Form:

#include "NSnochwas.inc"

fuer ${prefix}=TS in

#include "TSnochwas.inc"

aendern moechte.

Mittel der Wahl ist sed.

Von allen Versuchen, in denen ich mit " \ # . * um mich geschmissen habe, soll dieser hier als Beispiel dienen:


sed s/\#include \"NS.*/\#include \"${prefix}.*/ ${file} > ${file}.tmp

Ich bekomme nur "sed: No match."
Zum einen weiss ich nicht, wie ich das # da reinbekomme (oder wo sonst noch Fehler sind), zum anderen denke ich nicht, das das zweite .* funktioniert...

Wenn mir jemand von Euch in diesem Problem weiterhelfen koennte, waere das toll

Danke im Voraus
kamome

kamome
06-08-2004, 16:23
Nachdem ich nun gesehen habe, dass ich das .* (vermutlich) gar nicht benutzen sollte, habe ich es mal hiermit versucht:

sed s/"#"include" "\"NS/"#"include" "\"${prefix}/ ${file} > ${file}.tmp
Und tatsaechlich - keine Fehler_meldung_ mehr... es passiert (fuer mich erkennbar) aber auch nichts in den Dateien!?

Wer kann mir da weiterhelfen?

tia
kamome

peschmae
06-08-2004, 18:18
Quark. Überkompliziert. So. Jetzt noch ein Versuch von mir:


sed "s/#include \"NS/#include \"${prefix}/" -i test.txt


bearbeitet direkt in test.txt - also ohne aus einer Datei zu lesen und in eine andere Datei zu schreiben (d.h. eigentlich schon aber das merkst du nicht)

Die Variante aus dem zweiten Post geht aber auch. Bei mir. Bist du sicher dass du richtig geguckt hast? Die Änderungen liegen in ${file}.tmp - um die in die Originaldatei zurückzukriegen musst du -i verwenden wie oben oder mit mv ${file}.tmp ${file} die Datei verschieben.

MfG Peschmä

kamome
07-08-2004, 00:31
Danke Peschmae,

mit Deiner Erinnerung (.tmp) hast Du ins Schwarze getroffen :)
Die .tmp Dateien wurden tatsaechlich editiert, allerdings steht da jetzt immer "${prefix}" also die Variable nicht aufgeloest.

Leider bekomme ich mit dem von Dir vorgeschlagenen

sed "s/#include \"NS/#include \"${prefix}/" ${file} > ${file}.tmp
sed: -e expression #1, char 15: Unterminated `s' command

(das sed auf dem Rechner kann kein -i)

"Denkt" er vielleicht nur bis zum zweiten " ?
Daher habe ich " durch ' ersetzt:

sed 's/#include \"NS/#include\"${prefix}/" ${file} > ${file}.rmp

Und nun "geht" es wieder - so wie bei meiner zweiten Version: "${prefix}" statt ${prefix}, wieder nicht ersetzt.

Sowohl die " alsauch die ' verhindern wohl das Aufloesen der Variablen durch die shell.
!!!!!
!!!!!Ah, mit dieser Idee bin ich eben auf eine (dreiviertel) Loesung gekommen:
!!!!!

set locprefix=\"${prefix}
sed "s/#include..NS/#include ${locprefix}/" ${file} > ${file}.tmp

Das funktioniert! :D (Wenn es auch das syntaktische Problem umgeht statt es zu loesen)
Falls Du (oder andere) also noch eine "richtige" Loesung haben...
Ich wuerde mich sehr freuen da noch was zu erfahren.

Noch einmal vielen Dank bis hierher.

kamome

peschmae
07-08-2004, 08:43
Ich nutze die Bash - liegt wohl daran das mein Zeugs bei dir nicht ging. Die Variablen-Verhinderung bzw nichtverhinderung dort kenne ich - k.A. wie das bei der C-Shell ist.

Versuch mal das:


sed "s/#include \"NS/#include \""${prefix}/ < test.txt > test.txt.tmp


MfG Peschmä