Schrift
Wiki:Tipp zum Debugging: use Data::Dumper; local $Data::Dumper::Useqq = 1; print Dumper \@var;
[thread]8171[/thread]

Variablen in reg. Ausdrücken (s#$from#$to#g)



<< >> 10 Einträge, 1 Seite
Gast Gast
 2006-07-17 19:48
#68170 #68170
Hallo,

Ich möchte gerne etwa folgendes programmieren:

$file = "10abc.txt";
$from = "(\d\d).+?(\.\w+)";
$to = "\$1\$2";
$file =~ s#$from#$to#g;
print $file, "\n";


Es sollte heraus kommen: 10.txt


Die Variablen $from und $to sind dabei Zeichenketten, die
z.B. aus einer User-Eingabe stammen.
Ich kann also nicht mit konstanten Skalaren arbeiten.

Leider tut das Beispiel nicht und auch meine versuche mit
eval { } brachten bislang nichts.

Ich vermute es gibt eine einfache Lösung, auf die ich gerade nicht komme.

Danke schön
Ishka
 2006-07-17 20:54
#68171 #68171
User since
2003-08-04
771 Artikel
HausmeisterIn
[Homepage] [default_avatar]
Eine einfache Variante wäre
eval "\$file =~ s#$from#$to#g;";
wobei hier darauf hinzuweisen ist, daß hier der Benutzer den Programmablauf übernehmen kann, wenn er will, also das auf keinen Fall auf einem Server verwenden.
sub z{if(@_){1while$x[$k=rand 10];t($t=$x[$k]=1)}print map"$z[$x[$_]]$_".($_%3?
"":"\n"),1..9}sub t{$j=0;$x[$_+1]==$t&&($j+=2**$_)for 0..8;z,die"Gewinner $z[$t]
"if grep$_==($j&$_),7,56,73,84,146,273,292,448;z,die"Gleichstand\n"if@x>9&&!grep
!$_,@x}@x=4;@z=qw{. [ (};z$^T&1;while(<>){next if$_>9||$x[$_];t$t=$x[$_]=2;z 1}
grover
 2006-07-17 22:18
#68172 #68172
User since
2006-07-17
4 Artikel
BenutzerIn
[default_avatar]
Super Antwort, Danke.

So geht's. Wäre ich nicht drauf gekommen.
Auf eval war ich ja schon gekommen, aber ich habe das
ganz anders probiert.
Verstehe auch (ehrlich gesagt) nicht ganz warum es funktioniert.

Aber gut.

Vielen Dank
grover
 2006-07-17 22:26
#68173 #68173
User since
2006-07-17
4 Artikel
BenutzerIn
[default_avatar]
Und zur Beruhigung kurz noch:

Mir ist klar, das das Verwenden von User-Eingaben als Bestandteil
von Kommandozeilen, system-Aufrufen oder Ähnlichem
ein kaum zu überschauendes Risiko darstellen.

Das Kommando wird in der Shell von einem eingeloggten User verwendet.

Es ist Bestandteil eines file renaming utilities, welches dem User gestattet seine Dateien z.B. mit regulären Ausdrücken zu verändern.

Gruesse
renee
 2006-07-17 22:29
#68174 #68174
User since
2003-08-04
14371 Artikel
ModeratorIn
[Homepage] [default_avatar]
Du musst zwischen String-eval und Block-eval unterscheiden.

Die Erklärung dazu steht in perldoc -f eval:
Quote
In the first form, the return value of EXPR is parsed and
executed as if it were a little Perl program. The value of the
expression (which is itself determined within scalar context) is
first parsed, and if there weren't any errors, executed in the
lexical context of the current Perl program, so that any
variable settings or subroutine and format definitions remain
afterwards. Note that the value is parsed every time the "eval"
executes. If EXPR is omitted, evaluates $_. This form is
typically used to delay parsing and subsequent execution of the
text of EXPR until run time.

In the second form, the code within the BLOCK is parsed only
once--at the same time the code surrounding the "eval" itself
was parsed--and executed within the context of the current Perl
program. This form is typically used to trap exceptions more
efficiently than the first (see below), while also providing the
benefit of checking the code within BLOCK at compile time.
OTRS-Erweiterungen (http://feature-addons.de/)
Frankfurt Perlmongers (http://frankfurt.pm/)
--

Unterlagen OTRS-Workshop 2012: http://otrs.perl-services.de/workshop.html
Perl-Entwicklung: http://perl-services.de/
sid burn
 2006-07-17 23:33
#68175 #68175
User since
2006-03-29
1520 Artikel
BenutzerIn

user image
Quote
Es ist Bestandteil eines file renaming utilities, welches dem User gestattet seine Dateien z.B. mit regulären Ausdrücken zu verändern.

Hmm, auf welchen betriebssystem den? Bei "GNU/Linux" wird mit Perl immer das Tool "rename" mitgelifert das vom Meister Larry Wall selber programmiert wurde, und genau diese Aufgabe bereits erfüllt.

Code: (dl )
rename 'y/A-Z/a-z/' *

Dies macht aus allen Großbuchstaben kleine Buchstaben, aus dem aktuellen Verzeichnis.

Da das program ziemlich kurz ist, poste ich den Source Code mal, allerdings ohne Doku. Das Program unterliegt der Perl Lizenz.

Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
use strict;

use Getopt::Long;
Getopt::Long::Configure('bundling');

my ($verbose, $no_act, $force, $op);

die "Usage: rename [-v] [-n] [-f] perlexpr [filenames]\n"
unless GetOptions(
'v|verbose' => \$verbose,
'n|no-act' => \$no_act,
'f|force' => \$force,
) and $op = shift;

$verbose++ if $no_act;

if (!@ARGV) {
print "reading filenames from STDIN\n" if $verbose;
@ARGV = <STDIN>;
chop(@ARGV);
}

for (@ARGV) {
my $was = $_;
eval $op;
die $@ if $@;
next if $was eq $_; # ignore quietly
if (-e $_ and !$force)
{
warn "$was not renamed: $_ already exists\n";
}
elsif ($no_act or rename $was, $_)
{
print "$was renamed as $_\n" if $verbose;
}
else
{
warn "Can't rename $was $_: $!\n";
}
}
\n\n

<!--EDIT|sid burn|1153165456-->
Nicht mehr aktiv. Bei Kontakt: ICQ: 404181669 E-Mail: perl@david-raab.de
grover
 2006-07-18 00:32
#68176 #68176
User since
2006-07-17
4 Artikel
BenutzerIn
[default_avatar]
[quote=sid burn,17.07.2006, 21:33]
Quote
Es ist Bestandteil eines file renaming utilities, welches dem User gestattet seine Dateien z.B. mit regulären Ausdrücken zu verändern.

Hmm, auf welchen betriebssystem den? Bei "GNU/Linux" wird mit Perl immer das Tool "rename" mitgelifert das vom Meister Larry Wall selber programmiert wurde, und genau diese Aufgabe bereits erfüllt.

Code: (dl )
rename 'y/A-Z/a-z/' *

Dies macht aus allen Großbuchstaben kleine Buchstaben, aus dem aktuellen Verzeichnis.

Da das program ziemlich kurz ist, poste ich den Source Code mal, allerdings ohne Doku. Das Program unterliegt der Perl Lizenz.

Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
use strict;

use Getopt::Long;
Getopt::Long::Configure('bundling');

my ($verbose, $no_act, $force, $op);

die "Usage: rename [-v] [-n] [-f] perlexpr [filenames]\n"
unless GetOptions(
'v|verbose' => \$verbose,
'n|no-act' => \$no_act,
'f|force' => \$force,
) and $op = shift;

$verbose++ if $no_act;

if (!@ARGV) {
print "reading filenames from STDIN\n" if $verbose;
@ARGV = <STDIN>;
chop(@ARGV);
}

for (@ARGV) {
my $was = $_;
eval $op;
die $@ if $@;
next if $was eq $_; # ignore quietly
if (-e $_ and !$force)
{
warn "$was not renamed: $_ already exists\n";
}
elsif ($no_act or rename $was, $_)
{
print "$was renamed as $_\n" if $verbose;
}
else
{
warn "Can't rename $was $_: $!\n";
}
}
[/quote]
Quote
Bei "GNU/Linux" wird mit Perl immer das Tool "rename" mitgelifert das vom Meister Larry Wall selber programmiert wurde, und genau diese Aufgabe bereits erfüllt.


OK, wusste ich garnicht. Nicht schlecht.
Bei Linux sind ja immer Tonnen von Tools dabei, die man im Zweifel
nur nicht alle kennt.

Mein Script macht aber auch:

a) refi d3-6 filename.jpg
löscht das 3.-6. Zeichen aus dem Dateinamen, also entsteht fime.jpg

b) refi lE BlaBla.AVI
wandelt nur die Extension in Kleinbuchstaben, also BlaBla.avi

c) refi a.,01 10.txt
added 01 beim bzw. vorm Punkt, also entsteht 1001.txt

und und und ....

Diese reguläre Ersetzung ist quasi nur einer von vielen
Spezialfällen des Renamens.

Gruesse
grover
 2006-07-18 00:38
#68177 #68177
User since
2006-07-17
4 Artikel
BenutzerIn
[default_avatar]
Quote
Bei "GNU/Linux" wird mit Perl immer das Tool "rename" mitgelifert das vom Meister Larry Wall selber programmiert wurde, und genau diese Aufgabe bereits erfüllt.


Bei mir (SuSE 9.3// Perl 5.8.6) übrigens _nicht_ mit dabei.

Sorry, habe nicht verstanden das das Forum bei "Antwort mit Zitat" das ganze vorherige Posting bereits vollständig included.
betterworld
 2006-07-18 01:18
#68178 #68178
User since
2003-08-21
2613 Artikel
ModeratorIn

user image
Man könnte es auch so machen:
Code: (dl )
1
2
3
4
5
6
$file = "10abc.txt";
$from = "(\\d\\d).+?(\\.\\w+)";
$to = '$1$2';
$to = "qq#$to#";
$file =~ s/$from/$to/gee;
print $file, "\n";

Das ist im Prinzip auch nichts anderes als eval und daher genauso gefährlich.

Beachte die doppelten Backslashes in $from. Die sind nur da, weil "\d" sonst zu "d" wird. Wenn man den Code so schreibt wie Du, verschwinden die Backslashes sofort:
Code: (dl )
1
2
3
$from = "(\d\d).+?(\.\w+)";
print $from, "\n";
# Ausgabe: (dd).+?(.w+)

Wenn $from eine Benutzereingabe ist, ist es natuerlich nicht notwendig, doppelte Backslashes zu verwenden.
sid burn
 2006-07-18 14:25
#68179 #68179
User since
2006-03-29
1520 Artikel
BenutzerIn

user image
Quote
Bei mir (SuSE 9.3// Perl 5.8.6) übrigens _nicht_ mit dabei.

Ich schrieb auch "Betriebssystem". ;)

Probier mal "prename" aus.
Code: (dl )
1
2
3
4
5
6
$ ls -lha /usr/bin/rename
lrwxrwxrwx 1 root root 24 2006-03-03 15:46 /usr/bin/rename -> /etc/alternatives/rename
$ ls -lha /etc/alternatives/rename
lrwxrwxrwx 1 root root 16 2006-03-03 15:46 /etc/alternatives/rename -> /usr/bin/prename
$ dpkg -S /usr/bin/prename
perl: /usr/bin/prename


Quote
Mein Script macht aber auch:

Du kannst bei rename beliebigen Perl Code übergeben, du musst die variable "$_" verändern, und die Datei wird dann so abgeändert.

Die Sachen die du aufgelistet hast, kannst du auch so mit rename machen, allerdings sind deine Methoden da Sicherlich dann einfacher.

Allerdings kommen bei dir trotzdem Fragen auf. Was verstehst du unter Extension? Alles nach dem letzten Punkt? Wird auch ".tar.gz" als Extension erkannt?

Du schriebst "addes 01 vorm Punkt". Vor dem ersten, letzten oder vor alle Punkte?

rename ist vielleicht etwas "komplizierter". Hält dir dafür aber alle Möglichkeiten offen.\n\n

<!--EDIT|sid burn|1153218445-->
Nicht mehr aktiv. Bei Kontakt: ICQ: 404181669 E-Mail: perl@david-raab.de
<< >> 10 Einträge, 1 Seite



View all threads created 2006-07-17 19:48.