Schrift
[thread]8546[/thread]

/String+/ ersetzen mit String2 für alle /String+/

Leser: 1


<< |< 1 2 >| >> 12 Einträge, 2 Seiten
PerlProfi
 2006-12-03 19:54
#72215 #72215
User since
2006-11-29
340 Artikel
BenutzerIn
[default_avatar]
Ich habe einen langen String, der zum Beispiel so aussehen kann:
Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
$r->vor;
$r->vor;
$r->vor;
$r->drehe_rechts;
$r->vor;
$r->vor;
$r->drehe_links;
$r->vor;
$r->vor;
$r->vor;
$r->vor;
$r->vor;
drehe_um;
$r->vor;


Jetzt würde ich gerne alle '$r->vor;\n', die mindestens 2 mal hintereinander vorkommen mit 'vor(', der Anzahl von '$r->vor;\n' hintereinander, und ');\n' ersetzen.

So dass obiger String nachher so aussieht:
Code: (dl )
1
2
3
4
5
6
7
vor(3);
$r->drehe_rechts;
vor(2);
$r->drehe_links;
vor(5);
drehe_um;
$r->vor;


Wie kann man das machen?

Mein erster Ansatz war:
Code: (dl )
$string =~ s/(\$r->vor\;\n)+/vor\(ANZ\)\;\n/g;

Nur weiß ich nicht was anstelle von ANZ kommen muss.

MfG PerlProfi\n\n

<!--EDIT|PerlProfi|1165168579-->
topeg
 2006-12-03 21:00
#72216 #72216
User since
2006-07-10
2611 Artikel
BenutzerIn

user image
Ich würde es aus dem stehgreif so machen:
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
#!/usr/bin/perl
use strict;
use warnings;

my $str=
'$r->vor;
$r->vor;
$r->vor;
$r->drehe_rechts;
$r->vor;
$r->vor;
$r->drehe_links;
$r->vor;
$r->vor;
$r->vor;
$r->vor;
$r->vor;
drehe_um;
$r->vor;
';

my $cnt=0;
my @arr=();
for my $i (split(/(?<=;\n)/,$str))
{
push(@arr,$i) && next unless(@arr);
if($arr[-1] eq $i && $i=~/\$r->vor;\n/)
{ $cnt++; }
else
{
if($cnt)
{
$arr[-1]='vor('.($cnt+1).");\n";
$cnt=0;
}
push(@arr,$i);
}
}

print join ('',@arr);


Wobei es sicher noch eleganter geht. :-)

Edit:
Es gibt einen Einzeiler :-)
Code: (dl )
$str=$`.'vor('.scalar(@{[split(/;\n/,$&)]}).");\n".$' while($str=~/(?:\$r->vor;\n){2,}/s);
\n\n

<!--EDIT|topeg|1165173498-->
Linuxer
 2006-12-04 01:51
#72217 #72217
User since
2006-01-27
3875 Artikel
HausmeisterIn

user image
Hi,

ich finde zwar topeqs Lösung besser (ich meine nicht den Einzeiler! ;o) ), aber der Vollständigkeit halber (und weil ich es nun zusammengeschrieben habe), sei hier meine Lösung auch noch dargestellt.

Diese Variante betrachtet jeden String und zählt ihn mit; also werden zwei aufeinander folgende "drehe_rechts" ebenfalls zu "drehe_rechts (2)".

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
41
#!/usr/bin/perl
# vi:ts=4 sw=4 et:
use strict;
use warnings;

my $str = <<'EOS';
$r->vor;
$r->vor;
$r->vor;
$r->drehe_rechts;
$r->vor;
$r->vor;
$r->drehe_links;
$r->vor;
$r->vor;
$r->vor;
$r->vor;
$r->vor;
drehe_um;
$r->vor;
EOS

my @elements = split( /\n/, $str );
my ( $last, $cnt ) = ( '', 0);

for my $i ( 0 .. $#elements ) {

if ( $elements[$i] ne $last and $i != 0 ) {

print $last, ( $cnt > 1 ? "($cnt)" : ''), $/;

$cnt=1;
$last = $elements[$i];
next;
}

$last = $elements[$i];
$cnt++;
}

print $last, $/;
meine Beiträge: I.d.R. alle Angaben ohne Gewähr und auf Linux abgestimmt!
Die Sprache heisst Perl, nicht PERL. - Bitte Crossposts als solche kenntlich machen!
renee
 2006-12-04 09:54
#72218 #72218
User since
2003-08-04
14371 Artikel
ModeratorIn
[Homepage] [default_avatar]
Mein Vorschlag:
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
#!/usr/bin/perl

use strict;
use warnings;

my $str=
'$r->vor;
$r->vor;
$r->vor;
$r->drehe_rechts;
$r->vor;
$r->vor;
$r->drehe_links;
$r->vor;
$r->vor;
$r->vor;
$r->vor;
$r->vor;
drehe_um;
$r->vor;
';

$str =~ s!((?:\$r->vor;?\n?){2,})! my $anz = () = $1 =~ m/(\$r->vor;?\n?)/sg; my $string = "vor(".$anz.");\n"!esg;

print $str;
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/
topeg
 2006-12-04 10:19
#72219 #72219
User since
2006-07-10
2611 Artikel
BenutzerIn

user image
Hmm, ja. Die "e"-Option hatte ich vergessen. Dann würde ich es aber so schreiben:
Code: (dl )
$str =~ s|(?:\$r->vor;?\n?){2,}|'vor('.scalar(@{[split(/;\n/,$&)]}).");\n"|esg;

Das halte ich für etwas unkomplizierter. :-)

Edit: Meine Rechtschreibung, ohjeh...\n\n

<!--EDIT|topeg|1165220674-->
renee
 2006-12-04 10:33
#72220 #72220
User since
2003-08-04
14371 Artikel
ModeratorIn
[Homepage] [default_avatar]
Du solltest $& durch $1 ersetzen und im "suchteil" die matches einsammeln. Also
Code: (dl )
$str =~ s|((?:\$r->vor;?\n?){2,})|'vor('. @{[split(/;\n?/,$1)]} .");\n"|esg;


Das $& sollte man vermeiden, weil es den Regulären Ausdruck ausbremst (siehe perlvar).


Edit: Das scalar brauchst Du nicht, weil bei der Konkatenation sowieso Skalarer Kontext ist.\n\n

<!--EDIT|renee|1165221383-->
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/
topeg
 2006-12-04 10:56
#72221 #72221
User since
2006-07-10
2611 Artikel
BenutzerIn

user image
Man lernt halt nie aus.
Ärgerlicherweise sollte man ja auch $` und $' nicht verwenden.
GwenDragon
 2006-12-04 11:39
#72222 #72222
User since
2005-01-17
14554 Artikel
Admin1
[Homepage]
user image
[quote=topeg,03.12.2006, 20:00]Ich würde es aus dem stehgreif so machen:
...
Edit:
Es gibt einen Einzeiler :-)
Code: (dl )
$str=$`.'vor('.scalar(@{[split(/;\n/,$&)]}).");\n".$' while($str=~/(?:\$r->vor;\n){2,}/s);
[/quote]
Ich weiß nicht wie dir der Stehgreif (komisches Tier, solch ein Helferlein hätte ich auch gern) weiterhilft, aber ich meine, dass Regexe bei umfangreicheren Aktionen arg langsam werden können.
Andere "Parserlösungen" sind da sicherlich effizienter, wenn auch nicht so schnell zu schreiben. ;)

Aber darauf kommt es hier wohl nicht an.\n\n

<!--EDIT|GwenDragon|1165225315-->
die Drachin, Gwendolyn


Unterschiedliche Perl-Versionen auf Windows (fast wie perlbrew) • Meine Perl-Artikel

PerlProfi
 2006-12-04 18:43
#72223 #72223
User since
2006-11-29
340 Artikel
BenutzerIn
[default_avatar]
Danke für die vielen und vor allem schnellen Antworten.
Ich habe mich für die RegEx entschieden, es kommt nicht auf die Zeit an, und die Strings sind auch nicht unendlich lang.

Allerdings habe ich ein paar Fragen, die Regular Expression die ich jetzt verwende sieht so aus:
Code: (dl )
$content =~ s!(\$r->vor(;\n)){2,}!"vor(". @{[split(/;\n/, $&)]} .")$2"!eg;


Und zwar habe ich anstatt von $1, $& verwendet, da es mit $1 nicht funktioniert hat. Auch nicht wenn ich den ersten Teil komplett in Klammern gesetzt habe, das Ergebnis war immer 'vor(1)'.

Weiterhin habe ich das s am Ende weggelassen, als ich es ans Ende gesetzt habe hat sich das Ergebnis nicht verändert.
Könnte mir bitte jemand erklären wofür das s da ist?

Und am Anfang habe ich ?: ebenfalls weggelassen, weil ich leider nicht weiß was es zu bedeuten hat. Das Ergebnis war, als ich es an den Anfang gesetzt habe aber auch richtig.

MfG PerlProfi
renee
 2006-12-04 19:02
#72224 #72224
User since
2003-08-04
14371 Artikel
ModeratorIn
[Homepage] [default_avatar]
[quote=PerlProfi,04.12.2006, 17:43]Danke für die vielen und vor allem schnellen Antworten.
Ich habe mich für die RegEx entschieden, es kommt nicht auf die Zeit an, und die Strings sind auch nicht unendlich lang.

Allerdings habe ich ein paar Fragen, die Regular Expression die ich jetzt verwende sieht so aus:
Code: (dl )
$content =~ s!(\$r->vor(;\n)){2,}!"vor(". @{[split(/;\n/, $&)]} .")$2"!eg;


Und zwar habe ich anstatt von $1, $& verwendet, da es mit $1 nicht funktioniert hat. Auch nicht wenn ich den ersten Teil komplett in Klammern gesetzt habe, das Ergebnis war immer 'vor(1)'.
[/quote]

Meine Beispiele waren getestet und damit funktionieren sie garantiert. Es kommt darauf an, wie Du es eingebaut hast...

Quote
Weiterhin habe ich das s am Ende weggelassen, als ich es ans Ende gesetzt habe hat sich das Ergebnis nicht verändert.
Könnte mir bitte jemand erklären wofür das s da ist?

Und am Anfang habe ich ?: ebenfalls weggelassen, weil ich leider nicht weiß was es zu bedeuten hat. Das Ergebnis war, als ich es an den Anfang gesetzt habe aber auch richtig.

MfG PerlProfi

Das alles solltest Du in perlre, perlretut, perlreref und perlrequick nachlesen...\n\n

<!--EDIT|renee|1165251782-->
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/
<< |< 1 2 >| >> 12 Einträge, 2 Seiten



View all threads created 2006-12-03 19:54.