Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

suchen, finden und ersetzen

0 views
Skip to first unread message

Thomas Steinbach

unread,
Nov 17, 2009, 11:42:39 AM11/17/09
to
Hallo,

wie kann man mit Hilfe von perl Boardmitteln (also ohne sed oder awk, etc)
ein gegebenes Verzeichnis und seinen Unterverzeichnissen durchlaufen und
dabei
eine bestimmte zeile in den Dateien aendern, bzw. ersetzen. Also z.B. die
Zeile:

#!/usr/bin/perl

in ein

#!/usr/local/bin/perl

aendern/eretzen?


Thomas

Wolf Behrenhoff

unread,
Nov 17, 2009, 12:28:59 PM11/17/09
to
Thomas Steinbach wrote:
> Hallo,
>
> wie kann man mit Hilfe von perl Boardmitteln (also ohne sed oder awk, etc)
> ein gegebenes Verzeichnis und seinen Unterverzeichnissen durchlaufen und
> dabei
> eine bestimmte zeile in den Dateien aendern, bzw. ersetzen. Also z.B. die
> Zeile:

Also wenn es sich nur um eine Zeile handelt, w�rde ich immer
perl -pi -e 's/alt/neu/' *
vorschlagen. Das tuts aber nur f�r alle Dateien im Verzeichnis - und ist
ja auch sozusagen nicht "innerhalb" von Perl.

Innerhalb von Perl: ich w�rde wohl File::Find verwenden. In dem Code,
den du find �bergibst, musst du dann selbst die Dateien �ndern. Also ich
w�rde dann eine neue Datei �ffnen, die ge�nderten Daten da rein
schreiben und schlie�lich die alte Datei l�schen und die neu erstellte
dann umbenennen.

- Wolf

Ulli Horlacher

unread,
Nov 17, 2009, 5:54:17 PM11/17/09
to
Thomas Steinbach <stei...@gmx-topmail.de> wrote:

zB so mit rekursiver Funktion:

#!/usr/bin/perl -w

$subs = 's:^#!/usr/bin/perl:#!/usr/local/bin/perl:';
$dir = 'gegeben';

rs($dir);

sub rs {
my $dir = shift;
my ($file,@files,$fp);

if (opendir $dir,$dir) {
while ($file = readdir $dir) {
next if $file eq '.' or $file eq '..';
$fp = "$dir/$file";
if (-d $fp) {
rs($fp);
} elsif (-f $fp) {
push @files,$fp;
}
}
closedir $dir;
system qw(perl -p -i -e),$subs,@files if @files;
} else {
warn "cannot open $dir : $!\n";
}
}

--
Ullrich Horlacher Informationssysteme und Serverbetrieb
Rechenzentrum E-Mail: horl...@rus.uni-stuttgart.de
Universitaet Stuttgart Tel: ++49-711-685-65868
Allmandring 30 Fax: ++49-711-682357
70550 Stuttgart (Germany) WWW: http://www.rus.uni-stuttgart.de/

Thomas Steinbach

unread,
Nov 23, 2009, 12:48:02 PM11/23/09
to
Hallo,

>> [...]


> zB so mit rekursiver Funktion:

> #!/usr/bin/perl -w
> [...code...]

ja super, damit klappt es ganz gut und soweit konnte ich es
auch nachvollziehen. Danke fuer den Hinweis. Die Ersetzung
geht bei mir nicht so (Windows und Strawberry Perl), aber
mache da wohl besser einen anderen Thread auf, da ich nach
tagelangem Suchen nicht weiter komme.

Ich habe jetzt in Bezug auf Rekusion noch ein Verstaendnisproblem.

Zum einen ist ja opendir(DIRHANDLE, $dirname) definiert
und erst neuere (btw: ab wann?) perl Interpreter koennen auch
eine Referenz statt dem DIRHANDLE nutzen.

Jetzt ist es aber auch so das mir ein use strict das Verwenden einer
Referenz verbieten _wuerde_.

Wie kann ich das nun so machen, dass ich _keine_ Referenzen
auf das DIRHANDLE habe, sondern das DIRHANDLE selbst
_und_ use strict benutze, ohne das ich ein "no strict 'refs';"
setzen wuerde, um eben weiterhin eine starke Ueberpruefung
in dem Script beibehalten zu koennen.

Odr geht es nicht? Ich verstehe z.B. noch nicht wieso hier ein

readdir() attempted on invalid dirhandle DIR at shebang.pl line 22.
und
closedir() attempted on invalid dirhandle DIR at shebang.pl line 30.

kommt. Bzw. wird doch in jedem rekursiven Aufruf zwar der
$dirname uebergeben, aber dann doch wieder mit dem DIR Handle
_neu_ geoeffnet - genauso wie beim ersten Aufruf - oder? Und warum
wird dann die Rekursion abgebrochen?

Im Prinzip habe ich es genauso wie oben. Uueberpruefe aber noch auf
Textdatei und will dann erst eine Aktion auf die Datei loslasse).
Die Funktion filemod() ist jetzt aber nicht so wichtig.

Mich interessiert jetzt mehr warum die Rekursion nicht mit
dem DIRHANDLE funkt.

Teilweise kann ich die Fehler "abfedern", wenn ich vor closedir nochmal
schaue, ob der Datei-Pointer, bzw. variable auch auf ein Verzeichnis zeigt.

---snip---
#!perl -w

use strict;
#no strict 'refs';
use warnings;
use Cwd;

my $i = 0;
my @files;
my $dir = cwd;

recursive($dir);
filemod(\@files);

sub recursive {
$dir = shift; # @_
my ($file, $fp);
if( opendir(DIR, $dir) ) { #|| die("Can't open $dir: $!\n");
while( $file = readdir(DIR) ) {
next if( $file eq '.' || $file eq '..' );
$fp = "$dir/$file";
if( -d $fp ) {
recursive($fp);
}
elsif( -f $fp ) {
push(@files, $fp);
}
}
#if( -d $fp ) {
closedir(DIR);
#}
}else {
warn("Can't open $dir : $!\n");
}
} # end of recursive()

sub filemod {
if( defined($_[0]) ) {
my $tmp = $_[0];
foreach( @{$tmp} ) {
if( -T @{$tmp}[$i] ) {
print "@{$tmp}[$i]" , "\n";
}
$i++;
}
}
} # end of filemod()
---snap---

Thomas

Thomas Steinbach

unread,
Nov 23, 2009, 1:03:34 PM11/23/09
to
Hallo,

> Also wenn es sich nur um eine Zeile handelt, w�rde ich immer
> perl -pi -e 's/alt/neu/' *
> vorschlagen. Das tuts aber nur f�r alle Dateien im Verzeichnis - und ist
> ja auch sozusagen nicht "innerhalb" von Perl.

Danke fuer den Hinweis. Und mit Rekursion wie es Ulli vorgeschlagen
hat bin ich schon ganz gut weitergekommen, aber ich habe noch ein
Problem beim Erstzen. Das ist aber auch wieder ein neues Problem
und ich mache da besser einen neuen Thread auf.

Thomas

Ulli Horlacher

unread,
Nov 23, 2009, 6:42:24 PM11/23/09
to
Thomas Steinbach <stei...@gmx-topmail.de> wrote:

> Ich habe jetzt in Bezug auf Rekusion noch ein Verstaendnisproblem.
>
> Zum einen ist ja opendir(DIRHANDLE, $dirname) definiert
> und erst neuere (btw: ab wann?) perl Interpreter koennen auch
> eine Referenz statt dem DIRHANDLE nutzen.

Sollte seit etwa 10 Jahren so funktionieren.


> Jetzt ist es aber auch so das mir ein use strict das Verwenden einer
> Referenz verbieten _wuerde_.

Lass use strict weg :-)


> Wie kann ich das nun so machen, dass ich _keine_ Referenzen
> auf das DIRHANDLE habe, sondern das DIRHANDLE selbst

Dann geht die Rekursion nicht, weil DIRHANDLE global ist.


> kommt. Bzw. wird doch in jedem rekursiven Aufruf zwar der
> $dirname uebergeben, aber dann doch wieder mit dem DIR Handle
> _neu_ geoeffnet

Ja.


> Mich interessiert jetzt mehr warum die Rekursion nicht mit
> dem DIRHANDLE funkt.

Rekursion benoetigt lokale Variablen.
Das ist in allen Programmiersprachen so.

David Haller

unread,
Nov 24, 2009, 12:22:47 AM11/24/09
to

a) es sollte in scripten AFAIK immer #!/usr/bin/perl sein, auch unter
Windowsen, die ignorieren die Zeile ja eh.

$ ls -l /usr{,/local}/bin/perl{,5.*}
[..] /usr/bin/perl -> /usr/local/bin/perl*
[..] /usr/bin/perl5.00503*
[..] /usr/local/bin/perl*
[..] /usr/local/bin/perl5.10.0*
[.. noch ein paar "Leichen" ..]

Wobei /usr/local/bin/perl{,5.10.0} hardlinks sind.

b) schau dir mal die Ausgabe von

perl -MO=Deparse -pi.bak -e 's/foo/bar/;'

an. Dann die *komplette* Beschreibung von '-i[extension]' in
'perldoc perlrun' und dann noch 'perldoc File::Find' und ᅵberlege,
was man alles in der "wanted" Funktion unterbringen kᅵnnte ... ;)

HTH,
-dnh

--
A rule for life.
echo 16i[q]sa[ln0=aln100%Pln100/snlbx]sbA0D4D465452snlb xq |dc

Wolf Behrenhoff

unread,
Nov 24, 2009, 5:49:12 AM11/24/09
to
David Haller wrote:
> a) es sollte in scripten AFAIK immer #!/usr/bin/perl sein, auch unter
> Windowsen, die ignorieren die Zeile ja eh.

Wenn du perl perlprog.pl aufrufst, dann wird es schon ignoriert. Aber
wenn du z.B. unter Windows einen Apache hast, dann schaut der die Zeile
schon an und wirft dann natᅵrlich ggf. einen Fehler. Auch wenn man das
natᅵrlich mit "ScriptInterpreterSource registry" umgehen kann.

- Wolf

Peter J. Holzer

unread,
Nov 28, 2009, 8:51:47 AM11/28/09
to
On 2009-11-24 05:22, David Haller <dha...@spamgourmet.com> wrote:
> Thomas Steinbach <stei...@gmx-topmail.de> wrote:
>> wie kann man mit Hilfe von perl Boardmitteln (also ohne sed oder awk,
>> etc) ein gegebenes Verzeichnis und seinen Unterverzeichnissen
>> durchlaufen und dabei eine bestimmte zeile in den Dateien aendern,
>> bzw. ersetzen. Also z.B. die Zeile:
>>
>> #!/usr/bin/perl
>>
>> in ein
>>
>> #!/usr/local/bin/perl
>>
>> aendern/eretzen?
>
> a) es sollte in scripten AFAIK immer #!/usr/bin/perl sein, auch unter
> Windowsen, die ignorieren die Zeile ja eh.

Auf Windosen mag das egal sein, aber auf Unixen *muss* in der
Shebang-Zeile der richtige Pfad drin stehen. Wenn das Perl, das Du
einsetzen willst, in /usr/local/bin/perl ist (z.B. weil /usr/bin/perl
die Uralt-Version ist, die der Vendor glaubt, ausliefern zu m�ssen),
dann darf da nat�rlich nicht /usr/bin/perl stehen.

hp

0 new messages