Suche hilfe bei sed Aufruf für mehrere Dateien
Moin, ich hab hab hier ein kleines Problemchen, ich habe ein Verzeichnis mit einem Haufen .html Dateien, nennen wir die mal datei1.html bis datei5.html. In allen Dateien ist ein Bereich exakt gleich (das ist ein Menü): <a href="datei1.html" class="submenu" XXXX>YYYY<a href="datei2.html" class="submenu" XXXX>YYYY .... <a href="datei5.html" class="submenu" XXXX> YYYYYY Dabei können für XXXX noch irgendwelche Einträge kommen (sicher ist, dass der class-Parameter _nach_ der Referenz kommt. Die YYYYY unterscheiden sich natürlich auch alle :) Was soll geändert werden: in jeder Datei soll der class-Parameter des auf sich selbst zeigenden Links geändert werden, also in datei1.html soll nachher <a href="datei1.html" class="submenuUndNochwas" XXXX> stehen. so für eine einzelne Datei ist mir das schon klar und auch mir mehreren hatte ich an eine find Schleife gedacht, aber da hab ich so meine Probleme :( Ok, was mache ich: Für die einzelne Datei würde ich das so machen: sed -e 's/datei1.html\" class=\"submenu/&UndNochwas/g' datei1.html hier hab ich dann schon das erste Problem: ich will das wieder als datei1.html speicher, geht das anders als über eine 2. Datei und anschliessend umbenennen? Jetzt zu vielen Dateien: Meine erste Idee war in etwa so: find *.html -type f | xargs sed -e 's/$1\" class=\"submenu/&UndNochwas/g' $1 Problem (das sehen die Experten wahrscheinlich direkt :) ) sed löst das $1 nicht auf :( Neuer Versuch: find *.html -type f -exec sed -e 's/{}\" class=\"submenu/&UndNochwas/g' {} \; gleiches Prolbem sed löst das nicht auf :( Vermutung: das liegt an den Zeichenketten delimitern '', aber wie bekomme ich dann da eine Parametrisierung rein? Dann folgt noch das 2. Problem, ich will nachher ja den gleichen Dateinamen wiederhaben, sed -e'' a > a funktioniert ja nicht, dann bekomme ich eine leere Datei, also umleiten in was temporäres > abc.temp und wie bekomme ich das dann in diesem Schritt wieder umbenannt? xargs konsumiert den $1 irgendwie, so dass ich da nicht nochmal inder Form: find *.html -type f | xargs sed -e 's/$1\" class=\"submenu/&UndNochwas/g' $1 > temp ; cp temp $1 Da bekomme ich eine Fehlermeldung 'fehlende Zieldatei' :o und mit der anderen Idee (-exec) komme ich auch nicht weit, weil da ja die einzelnen Zeilen an xargs geschickt werden... Ich bin etwas ratlos... Andreas
"A.Loesch" <suseliste@litcas.de>
Ok, was mache ich: Für die einzelne Datei würde ich das so machen: sed -e 's/datei1.html\" class=\"submenu/&UndNochwas/g' datei1.html
Jetzt zu vielen Dateien:
so sollte es gehen: for f in `find verzeichnis -name "*.html"` do sed -e "s/$f\" class=\"submenu/&UndNochwas/g" < $f > $f.x mv $f.x $f done Wie funktioniert's: for f in `find ...` ist eine Schleife über alle Dateinamen, welche find findet. sed ... $f $f ist die "Laufvariable". Noch ein paar Bemerkungen:
find *.html -type f | xargs sed -e 's/$1\"class=\"submenu/&UndNochwas/g' $1 Problem (das sehen die Experten wahrscheinlich direkt :) ) sed löst das $1 nicht auf :(
logisch mit $1, $2 usw wird auf die Parameter eines Shellskriptes zugegriffen. Generell: Auflösen der Variablennamen zu Werten wird von der Shell erledigt, nicht von sed. sed bekommt also nicht $1 "zu sehen", sondern den Wert des ersten Parameters des Shellscriptes oder falls nicht angegeben der leere String.
Dann folgt noch das 2. Problem, ich will nachher ja den gleichen Dateinamen wiederhaben, sed -e'' a > a funktioniert ja nicht, dann bekomme ich eine leere Datei, also umleiten in was temporäres > abc.temp und wie bekomme ich das dann in diesem Schritt wieder umbenannt? gar nicht. immer so wie oben gezeigt: proggi < file > file.x mv file.x file (wobei es natürlich nicht .x heissen muß, irgend ein anderer Name tuts auch).
xargs konsumiert den $1 irgendwie, so dass ich da nicht nochmal inder Form:
find *.html -type f | xargs sed -e 's/$1\" class=\"submenu/&UndNochwas/g' $1 > temp ; cp temp $1
Das macht was ganz anderes! 1. $1 sie meine Bemerkung von oben 2. find ... | xargs proggi ruft proggi mit sovielen Dateinamen (genauer Ausgaben von find) auf, wie es das Betriebsystem zulässt. (Jdes Betriebssystem hat eine obere Grenze was die Länge der Parameter eines Programmes angeht). Reicht ein Aufruf von proggi nicht, wird eben noch ein zweiter usw. abgesetzt. 3. find ... | xargs proggi ; cp temp $1 - $1 s.o - xargs s.o Der cp Befehl wird erst ausgeführt, wenn das "find .. | xargs .." Kommando vollständig abgearbeitet ist, also genau einmal. Bye Jürgen -- Dr.rer.nat. Juergen Vollmer, Viktoriastrasse 15, D-76133 Karlsruhe Tel: +49(721) 9204871 Fax: +49(721) 24874 Juergen.Vollmer@[informatik-vollmer.de|alumni.uni-karlsruhe.de|acm.org] www.informatik-vollmer.de
Ich bins nochmal:
so sollte es gehen:
for f in `find verzeichnis -name "*.html"` do sed -e "s/$f\" class=\"submenu/&UndNochwas/g" < $f > $f.x mv $f.x $f done
Da hab ich mit dem for f in einkleines Problem :) for f in `find . -name "*.html"` do echo $f done Liefert: find . -name "*.html" Wenn ich for f in `find /home/andreas/test -name "*.html"` verwende bekomme ich find /home/andreas/test -name "*.html" Nur ein for f in `find *.html` liefert das gewünschte... Andreas
Hallo, Am Fri, 09 Jan 2004, A.Loesch schrieb:
Da hab ich mit dem for f in einkleines Problem :)
for f in `find . -name "*.html"` do echo $f done
Liefert: find . -name "*.html"
Dann hast du in deinem script '' statt `` verwendet. -dnh --
Quatsch. Ich will ein Internet ohne Werbemüll. Und ohne AOL. AOL! -- R. Schwentker und M. Karcher
Hallo, David Haller, Friday, January 09, 2004 8:55 PM
Am Fri, 09 Jan 2004, A.Loesch schrieb:
Da hab ich mit dem for f in einkleines Problem :)
for f in `find . -name "*.html"` do echo $f done
Liefert: find . -name "*.html"
Dann hast du in deinem script '' statt `` verwendet.
Jau :) THX das wars... Vielen Dank an alle Helfer jetzt funktioniert auch alles, Andreas, der sich doch mal mehr mit Shellscripts auseinandersetzen muss.....
Juergen.Vollmer@informatik-vollmer.de , Friday, January 09, 2004 7:53 PM
"A.Loesch" <suseliste@litcas.de>
Ok, was mache ich: Für die einzelne Datei würde ich das so machen: sed -e 's/datei1.html\" class=\"submenu/&UndNochwas/g' datei1.html
Jetzt zu vielen Dateien:
so sollte es gehen:
Danke, werde ich mal in Ruhe testen, nur eine Sache verstehe ich nicht:
for f in `find verzeichnis -name "*.html"` do sed -e "s/$f\" class=\"submenu/&UndNochwas/g" < $f > $f.x mv $f.x $f done
.... < $f > $f.x Warum dieses < und > ? Der sed-call ist doch entweder stdin oder Dateiname, kann man den < nicht auch weglassen?
Wie funktioniert's: [...]
Noch ein paar Bemerkungen:
Danke :) Andreas
"A.Loesch" <suseliste@litcas.de>
.... < $f > $f.x Warum dieses < und > ? Der sed-call ist doch entweder stdin oder Dateiname, kann man den < nicht auch weglassen?
den < (Eingabeumleitung) kann man weg lassen, > nicht, denn sed schreibt seine Ausgabe nach stdout. Macht der Gewohnheit :-) Jürgen -- Dr.rer.nat. Juergen Vollmer, Viktoriastrasse 15, D-76133 Karlsruhe Tel: +49(721) 9204871 Fax: +49(721) 24874 Juergen.Vollmer@[informatik-vollmer.de|alumni.uni-karlsruhe.de|acm.org] www.informatik-vollmer.de
Juergen.Vollmer@informatik-vollmer.de , Saturday, January 10, 2004 4:48 PM
"A.Loesch" <suseliste@litcas.de>
.... < $f > $f.x Warum dieses < und > ? Der sed-call ist doch entweder stdin oder Dateiname, kann man den < nicht auch weglassen?
den < (Eingabeumleitung) kann man weg lassen, > nicht, denn sed schreibt seine Ausgabe nach stdout.
Macht der Gewohnheit :-)
na dann ist ja gut ;) ich wollte das nur verstehen, ob da ein Grund hintersteckte. Andreas
Hallo, Am Fri, 09 Jan 2004, A.Loesch schrieb:
Für die einzelne Datei würde ich das so machen: sed -e 's/datei1.html\" class=\"submenu/&UndNochwas/g' datei1.html
Das Muster waere mir ein bisserl zu "ungenau"...
hier hab ich dann schon das erste Problem: ich will das wieder als datei1.html speicher, geht das anders als über eine 2. Datei und anschliessend umbenennen?
Nein.
Jetzt zu vielen Dateien: Meine erste Idee war in etwa so:
find *.html -type f | xargs sed -e 's/$1\" class=\"submenu/&UndNochwas/g' $1
1. Autsch. Das darf nicht laufen, es sei denn, du hast im aktuellen Verzeichnis Unterverzeichnisse mit "irgendwas.html" im Namen -- oder keine einzige Datei, die 'irgendwas.html' heisst. Denn find bekommt das *.html nie zu sehen, weil das die shell aufloest. Dich hat bisher wohl nur gerettet, dass du keine .html im aktuellen Verzeichnis hast, das *.html also von der shell zu nichts expandiert wird, find also ohne Pfad aufgerufen wird und dann sein Default nimmt und einfach im aktuellen Verzeichnis sucht. 2. Autsch. Wenn, dann musst du 'xargs -n 1' verwenden.
Problem (das sehen die Experten wahrscheinlich direkt :) ) sed löst das $1 nicht auf :(
1. sed loest $1 nie auf 2. die shell loest schon wg. den '' nicht auf 3. die shell ist bei der Konstruktion gar nicht beteiligt
Neuer Versuch:
find *.html -type f -exec sed -e 's/{}\" class=\"submenu/&UndNochwas/g' {} \;
gleiches Prolbem sed löst das nicht auf :(
Siehe 1. und 2. oben. ==== UNGETESTET! ==== for f in `find . -type f -name '*.html' -maxdepth 1`; do sed -e "/$f/s/\(.*a href=\"$f\" class=\"\)submenu\(\".*\)/\1submenuUndNochwas\2/g" \ "$f" > "$f.tmp" && mv -f "$f.tmp" "$f" done ==== -dnh -- 95: PGP-Keysigning-Party Kultiges Zusammensitzen und gemeinsames Murmeln magischer Zahlen. (Gert Döring)
David Haller, Friday, January 09, 2004 9:22 PM
Am Fri, 09 Jan 2004, A.Loesch schrieb:
Für die einzelne Datei würde ich das so machen: sed -e 's/datei1.html\" class=\"submenu/&UndNochwas/g' datei1.html
Das Muster waere mir ein bisserl zu "ungenau"...
*grins* [Viel interessantes]
==== UNGETESTET! ==== for f in `find . -type f -name '*.html' -maxdepth 1`; do sed -e "/$f/s/\(.*a href=\"$f\" class=\"\)submenu\(\".*\)/\1submenuUndNochwas\2/g" \ "$f" > "$f.tmp" && mv -f "$f.tmp" "$f" done
Das wird ich mir mal in aller Ruhe ansehen, staun.... gibt es so ganz spontan ein _gutes_ must have Buch zu dem Thema? Oder eine oder 2 wirklich gute Seiten im Netz? Andreas
Hallo, Am Fri, 09 Jan 2004, A.Loesch schrieb:
David Haller, Friday, January 09, 2004 9:22 PM [..] Das wird ich mir mal in aller Ruhe ansehen, staun....
Eine Rueckmeldung, ob's tatsaechlich tut, ist erwuenscht ;)
gibt es so ganz spontan ein _gutes_ must have Buch zu dem Thema? Oder eine oder 2 wirklich gute Seiten im Netz?
http://www.selflinux.de/ Ansonsten: (Advanced-) Bash-Programming-HOWTO, sed & awk [O'Reilly] u.a.m... Aber... Besonders ans Herz legen moechte ich dir die man- und infopages (auf Englisch! Zumindest mal anschauen solltest du die auch wenn dein Englisch eigentlich nicht reicht, denn die deutschen Uebersetzungen sind oft nicht vollstaendig, und/oder veraltet, und/oder falsch). Die sind "nicht einfach", es fehlen meist Beispiele, sie sind aber die beste _Referenz_ (ausser dem Quelltext) der Programme. Anders gesagt: man- und infopages sind ein "must read", alles andere ist "Zucker", der Konzepte erklaert, Beispiele liefert usw... Und generell muss man die Doku (z.B. zur bash) immer mit der Realitaet abgleichen, z.B. mittels man/infopage und der Ausgabe von "programm --help" (oder "-help" o.ae.). -dnh, der fast ausschliesslich aus man- und infopages sowie gelegentlich den Quellen, READMEs usw. lernt. -- Das heißt also Absenkung des Nach..., des, des, des, des, des, na, des Alters, des Alters der Kinder, wenn sie, des Nachzugalters; dann kommt der fünfte Punkt, und der sechste Punkt kommt dann sicherlich die Frage gleichge..., äh, nicht gleichgeschle..., sondern äh, ... Edmund S. 20.1.2002, in 'S.Christiansen', ARD
Hallo, David Haller, Saturday, January 10, 2004 12:34 AM
Am Fri, 09 Jan 2004, A.Loesch schrieb:
David Haller, Friday, January 09, 2004 9:22 PM [..] Das wird ich mir mal in aller Ruhe ansehen, staun....
Eine Rueckmeldung, ob's tatsaechlich tut, ist erwuenscht ;)
Wird gegeben :) ich habs noch nicht ganz durchschaut und auch ncoht nicht angewendet aber kommt... [...]
Aber... Besonders ans Herz legen moechte ich dir die man- und infopages (auf Englisch! Zumindest mal
Das Buch muss nicht Deutsch sein ;) aber sinnvolle Beispiele helfen mir immer sehr... Ich wird die man pages noch mal ausführlicher studieren. Dann noch mal zu Deiner ersten Antwort:
sed -e 's/datei1.html\" class=\"submenu/&UndNochwas/g' datei1.html
Das Muster waere mir ein bisserl zu "ungenau"...
könntest Du mit wenigen Worten erläutern, warum zu ungenau? Evtl. ist das für meien Zweck doch richtig, denn ich kann definitiv sagen, dass diese zeile in der Datei _genau_ einmal vorkommt... Dein Vorschlag war dieses hier, wobei natürlich $f == datei1.html wäre: sed -e "/$f/s/\(.*a href=\"$f\" class=\"\)submenu\(\".*\)/\1submenuUndNochwas\2/g" "$f" Andreas
Hallo, Am Sat, 10 Jan 2004, A.Loesch schrieb:
David Haller, Saturday, January 10, 2004 12:34 AM
Am Fri, 09 Jan 2004, A.Loesch schrieb: [..] Dann noch mal zu Deiner ersten Antwort:
sed -e 's/datei1.html\" class=\"submenu/&UndNochwas/g' datei1.html
Das Muster waere mir ein bisserl zu "ungenau"...
könntest Du mit wenigen Worten erläutern, warum zu ungenau? Evtl. ist das für meien Zweck doch richtig, denn ich kann definitiv sagen, dass diese zeile in der Datei _genau_ einmal vorkommt...
Aber kommt auch datei1.html" class="submenu nur genau einmal vor? Wenn ja, dann reicht das natuerlich als Muster. -dnh --
Naja spiele ich halt wieder Frisbee mit der NT CD. Funktioniert nicht. Stürzt immer ab. -- Hans Pueschel in dasr
David Haller wrote:
Hallo,
Am Fri, 09 Jan 2004, A.Loesch schrieb:
David Haller, Friday, January 09, 2004 9:22 PM
[..]
==== UNGETESTET! ==== for f in `find . -type f -name '*.html' -maxdepth 1`; do sed -e "/$f/s/\(.*a href=\"$f\" class=\"\)submenu\(\".*\)/\1submenuUndNochwas\2/g" \ "$f" > "$f.tmp" && mv -f "$f.tmp" "$f" done ==== [...]
Das wird ich mir mal in aller Ruhe ansehen, staun....
Eine Rueckmeldung, ob's tatsaechlich tut, ist erwuenscht ;)
so, hat lang gedauert :) aber jetzt bin ich endlich zum testen und ausprobieren gekommen, es klappt nicht ganz. Das Problem ist, dass ich mit der find Geschichte Dateinamen der Form ./name.html bekomme, d.h. hier muss noch mit basename o.ä. das führende ./ entfernt werden. dabei bin ich auf ein anderes Problem gestossen: irgendwie ist es mir nicht gelungen, über ff=basename $f die Umwandlung im Script vorzunehmen.... mit etwas googeln hab ich dann das hier gefunden und das funktioniert: ff=${f##*/} so, also das noch for die sed-zeile und da s/f/ff/ dann gehts :) Danke nochmal, Andreas
Hallo, Am Thu, 12 Feb 2004, A.Loesch schrieb:
David Haller wrote:
Am Fri, 09 Jan 2004, A.Loesch schrieb:
David Haller, Friday, January 09, 2004 9:22 PM
[..] ==== UNGETESTET! ==== for f in `find . -type f -name '*.html' -maxdepth 1`; do sed -e "/$f/s/\(.*a href=\"$f\" class=\"\)submenu\(\".*\)/\1submenuUndNochwas\2/g" \ "$f" > "$f.tmp" && mv -f "$f.tmp" "$f" done ==== [...]
Das wird ich mir mal in aller Ruhe ansehen, staun....
Eine Rueckmeldung, ob's tatsaechlich tut, ist erwuenscht ;)
so, hat lang gedauert :) aber jetzt bin ich endlich zum testen und ausprobieren gekommen, es klappt nicht ganz.
Das Problem ist, dass ich mit der find Geschichte Dateinamen der Form
./name.html
bekomme, d.h. hier muss noch mit basename o.ä. das führende ./ entfernt werden.
Kann man schon im 'find' anpassen: for f in `find . -type f -name '*.html' -maxdepth 1 -printf '%p\n'`; Siehe 'man find'.
dabei bin ich auf ein anderes Problem gestossen: irgendwie ist es mir nicht gelungen, über ff=basename $f die Umwandlung im Script vorzunehmen....
Da fehlten wohl die ``: ff="`basename \"$f\"`" (beachte da quoting, das ist wichtig falls (u.a.) Leerzeichen im Dateinamen vorkommen koennen).
mit etwas googeln hab ich dann das hier gefunden und das funktioniert: ff=${f##*/}
so, also das noch for die sed-zeile und da s/f/ff/ dann gehts :)
Das kannst du auch direkt einbauen (falls du nicht die direkte Methode gleich beim find machen willst, bzw. ist nur als Ergaenzung gedacht: sed -e "/${f##*/}/s/\(.*a href=\"${f##*/}\" class=... ^^^^^^^^ ^^^^^^^^ Ob du jetzt an beiden Stellen das willst weiss ich nicht. ;) Aber wie geschrieben: einfacher ist's wenn du den Pfad erst gar nicht im $f hast, d.h. wenn du o.g. find-Variante mit dem "-printf '%p\n'" verwendest. Ich hoffe, du machst dir auch die Muehe, das anhand der manpages nachzuvollziehen ;) -dnh -- Einer der beiden hat sich damals noch ziemlich auf den Schlips getreten gefühlt weil der Azubi (also meine Wenigkeit) denen klargemacht hat das die Idee scheiße ist. -- Thorsten Dahm
participants (3)
-
A.Loesch
-
David Haller
-
Dr. Jürgen Vollmer