suchen ersetzen in Text dateien

pinky

pinky

König
Hi!
ich habe folgendes Problem: Von einem Verzeichnis ausgehend gibt es mehrere html Dateien (auch in unterverzeichnissen). Mein Ziel ist es jetzt alle HTML Dateien durch zu gehen und nach Abschnitten wie:
Code:
...
<!-- ersetzen-anfang -->
...
hier kann beliebig viel kommen
...
<!- - ersetzen-ende -->
...
zu suchen und diesen dann durch den Inhalt einer anderen Datei zu ersetzen.

Hat jemand eine Idee wie und mit welchen Mitteln ich das am besten erreichen kann und vielleicht sogar ein kurzes Beispiel?

Danke!
 
Hatte hier was reingeschrieben aber bei genauerer Betrachtung... wird's dir nicht helfen.
Das Posting kann geloescht werden.

Niels
 
Zuletzt bearbeitet:
hi

also ich hatte mir damals nen kleines perlscript geschrieben mit regulären ausdrücken.

das funktionierte dann in etwa so: ./meinscript datei textsuchen textersetzen

dafür musste halt nur reguläre ausdrücke verwende. leider hab ich das script aber im moment nicht vorliegen. aber du hast auf jedenfall nen kleinen denkanstoss.

mfg frank
 
Hmm... OK dann poste ich meins doch noch... ;)


#!/usr/bin/perl
#Es wird nach dem zu ersetzenden Begriff gefragt
print "Welcher Begriff soll ersetzt werden?\n";
$search = <STDIN>;
chomp ($search);

#Wodurch soll der Begriff ersetzt werden?
print "Wodurch soll der Begriff ersetzt werden?\n";
$replace = <STDIN>;
chomp ($replace);

print "Welches Dateiformat soll behandelt werden? (txt, c, html, etc.)\n";
$format = <STDIN>;
chomp ($format);

#Alle HTML-Dateien werden in das Array eingelesen.
@Allhtml = glob($format);

#Anweisungen was mit jeder Datei zu geschehen hat (foreach).
foreach $dateien (@Allhtml)
{
chomp ($dateien);
#Die Dateien werden geoeffnet
open (DATA, "$dateien") || die "konnte die Datei nicht oeffnen\n";
#Solange noch etwas in der Datei steht, fuehre sed-Aktion aus
while (<DATA>)
{
s/$search/$replace/g;
#Die geaenderten Dateien werden in einem neuen Array gespeichert.
push (@content, $_);
}
#Die Datei wird nach der Bearbeitung geschlossen.
close (DATA);
#Die Datei wird zum schreiben geoeffnet
open (WRITE, ">$dateien") || die "konnte Datei nicht beschreiben\n";
#Die Datei wird mit dem Inhalt des Arrays ueberschrieben.
print WRITE @content;
#die fertige Datei wird geschlossen.
close (WRITE);
#Das Array wird geleert (optional, ist bei Perl eigentlich nicht erforderlich)
@content = ();
}
 
Auf die Schnelle:

Code:
#!/usr/bin/perl

use strict;

my ($htmlfile, $substfile) = @ARGV;
open FILE, "< $substfile" or die "Can't open $substfile : $!";
my @substtext = <FILE>;
close FILE;
open OLDFILE, "< $htmlfile" or die "Can't open $htmlfile : $!";
open NEWFILE, "> $htmlfile.bak" or die "Can't open $htmlfile.bak : $!";
my $subst = 0;
foreach (<OLDFILE>) {
	print NEWFILE $_ if (! $subst);
	if (/^<!-- ersetzen-anfang -->/) {
		map {print NEWFILE $_} @substtext;
		$subst = 1
	} elsif (/^<!-- ersetzen-ende -->/) {
		print NEWFILE $_;
		$subst = 0
	}
}
close OLDFILE;
close NEWFILE;
rename "$htmlfile.bak", "$htmlfile"

Anschliessend aufrufen mittels

Code:
programmname htmlfile substfile

edit: Geprüft!
 
Zuletzt bearbeitet:
Hmm, das sieht alles nach nützlichen Scripts aus, aber darf ich nochmal nachfragen, was genau gewünscht ist?
Ich habe es so verstanden:

1. Du hast ein Verzeichnis mit Unterverzeichnissen, in denen sich html-Dateien befinden
2. Dort willst du, dass in allen html Dateien zwischen zwei bestimmten Zeilen einschließlich dieser Zeilen alles ersetzt wird, und zwar durch
3. den Inhalt einer anderen Datei

Daraus folgt, dass wir vier Eingaben brauchen:
1. Das Verzeichnis
2. $anfang und $ende
3. Die Datei die ersetzen soll

Frage: ist die Datei aus der der Text eingefügt werden soll immer dieselbe oder eine andere?

Anhand dieser Informationen könnte man dann eins dieser Scripte verändern oder ein neues schreiben, was deinem Wunsch dient.
 
Hallo,
erstmal danke für die vielen Antworten.
Hier noch mal das ganze etwas konkreter an den Fragen von jesusgeek.

jesusgeek schrieb:
1. Du hast ein Verzeichnis mit Unterverzeichnissen, in denen sich html-Dateien befinden
2. Dort willst du, dass in allen html Dateien zwischen zwei bestimmten Zeilen einschließlich dieser Zeilen alles ersetzt wird, und zwar durch
3. den Inhalt einer anderen Datei

genau.

Daraus folgt, dass wir vier Eingaben brauchen:
1. Das Verzeichnis
2. $anfang und $ende
3. Die Datei die ersetzen soll

Das könnte man alles im script am Anfang als Konstante einprogrammieren.
Das Startverzeichnis sollte sich aus dem Verzeichnis indem sich das script befindet ergeben und anfang+end tags sowie die Datei mit dem Inhalt der eingefügt werden soll sind statisch.
Das script soll später im obersten Verzeichnis liegen, einfach mit ./foo gestartet werden und dann von dem Verzeichnis indem sich das script befinden ausgehend rekursiv durch alle html dateien gehen.
 
Zuerst das Skript foo.sh:

Code:
#!/usr/local/bin/bash

anfang="<!-- ersetzen-anfang -->"
ende="<!-- ersetzen-ende -->"
substfile="subst.txt"

find . -iname "*.html" -exec ./subst.pl "{}" "$substfile" "$anfang" "$ende" \;

und das zugehörige subst.pl:

Code:
#!/usr/bin/perl

use strict;

my ($htmlfile, $substfile, $anfang, $ende) = @ARGV;
open FILE, "< $substfile" or die "Can't open $substfile : $!";
my @substtext = <FILE>;
close FILE;
open OLDFILE, "< $htmlfile" or die "Can't open $htmlfile : $!";
open NEWFILE, "> $htmlfile.bak" or die "Can't open $htmlfile.bak : $!";
my $subst = 0;
foreach (<OLDFILE>) {
        print NEWFILE $_ if (! $subst);
        if (/^$anfang/) {
                $subst = 1;
                map {print NEWFILE $_} @substtext
        } elsif (/^$ende/) {
                print NEWFILE $_;
                $subst = 0
        }
}
close OLDFILE;
close NEWFILE;
rename "$htmlfile.bak", "$htmlfile"

Beides in das Suchverzeichnis legen und mit ./foo.sh starten.
 
Hallo
Viele Wege führen nach Rom.
Weil sowas häufiger vorkommt,
hier noch (m)ein Vorschlag.
Nein kein Einzeiler. ;)
Der einzige Unterschied ist hierbei, dass es nicht abbricht wenn eine Datei nicht geöffnet oder geschlossen werden kann.
Es gibt nur die Fehlermeldung aus und macht weiter.
Dafür nutze ich den eval Block und fange das SIGNAL{__DIE__} ab.
Code:
#!/usr/bin/perl -w
use strict;
use File::Slurp;
unless (@ARGV){print "Use $0 File or Glob like *html..\n";exit}
my $t='/tmp/text';
my $repl=read_file($t);
my $cn=0;
for (@ARGV){
[color=blue]eval {
local $SIG{'__DIE__'};
my $k =read_file($_) or die "Cant read $_";
$k=~s!(.*?)[<]head>.*[<]/head[>](.*)!$1$repl$2!igs;
write_file($_ , \$k) or die "Cant write $_";$cn++ if ($1 && $2)};[/color]
print $@ if $@;
}
print "All down $cn Files written\n";
File::Slurp ist sehr nützlich, wie man sieht. erkürzt den Code erheblich.
Ich habe hier einen HTML-HEAD Block genommen, das kann aber angepasst werden.
Das einfach mit einer Dateiliste aufrufen, oder File::Finde benutzen und ein @Array füllen.

Gruß Wolfgang
 
Interessante Lösung, ich schau sie mir mal genauer an.
 
Meine Lösung

Hi, ich hatte ein ähnliches Problem. Ich wollte rekursiv durch die Ordner gehen und alle dfm und nfm Dateien verändern. Hier meine Lösung:
Code:
&find('.');
exit;

sub wanted {

	return unless -f $_;
	if (($name =~/\..fm/)&&!($name =~/\..fm.+/)){
		$filename = $_; 
		open(DATA, $filename) || die " Fehler bei öffnen der Datei $name \n";
		foreach(<DATA>){
			if(/xAnchors/){
				$success = true;
			}
		} 
		if ($success){
			foreach(<DATA>){
				s/xAnchors/Anchors/g;
				s/anLeft/akLeft/g;
				s/anTop/akTop/g;
				s/anRight/akRight/g;
				s/anBottom/akBottom/g;
				push(@content, $_);			
			}
			close (DATA);
			open (WRITE, ">$filename") || die "konnte Datei nicht oeffnen";
			print WRITE @content;
			close (WRITE);
			@content = ();
		}
	}
        $success = false
}
 
Zuletzt bearbeitet von einem Moderator:

Ähnliche Themen

Verzeichnis mit 1200 Dateien auf Verweise in Textdateien checken

Suchen und Ersetzen mit regulärem Ausdruck

Unterschiedlichen Text in mehrere Dateien finden und löschen / ersetzen

Zeilenweise suchen, löschen und ersetzen / Inhalt einfügen

Suchen und ersetzen in HTML Dokumenten

Zurück
Oben