Schrift
[thread]12460[/thread]

Texte in Zeichenkette tauschen



<< >> 9 Einträge, 1 Seite
Benutzer
 2008-09-09 11:02
#114397 #114397
User since
2008-06-18
7 Artikel
BenutzerIn
[default_avatar]
Hallo,

ich versuche in einer Zeichenkette bestimmte Muster zu tauschen. Alle Muster kommen mehrfach in der Zeichenkette vor und sollen alle ersetzt werden.
Das Problem ist, dass die Zeichenkette nur einmal durchlaufen werden darf, weil sonst bereits ersetzte Muster erneut ersetzt werden.
Code: (dl )
1
2
3
4
5
%tausche = (
'eins' => 'zwei',
'zwei' => 'eins',
'drei' => 'vier');
$zeichen = 'bla eins bla zwei bla drei bla vier';


Ergebnis soll sein:
Code: (dl )
$zeichen = 'bla zwei bla eins bla vier bla vier'


und nicht:
Code: (dl )
$zeichen = 'bla eins bla eins bla vier bla vier'


So geht's NICHT:
Code: (dl )
@ergebnis = map {$zeichen =~ s/$_/$tausche{$_}/g} keys %tausche;


Hat jemand eine zündende Idee? Ich steh grad auf dem Schlauch.

Danke und Grüsse
moritz
 2008-09-09 11:18
#114398 #114398
User since
2007-05-11
923 Artikel
HausmeisterIn
[Homepage]
user image
Code (perl): (dl )
1
2
my $regex = join '|', map quotemeta, keys %tausche;
$zeichen =~ s/($regex)/$tausche{$1}/g;
Benutzer
 2008-09-09 12:01
#114402 #114402
User since
2008-06-18
7 Artikel
BenutzerIn
[default_avatar]
Danke Moritz,

du baust indirekt eine ODER-Verknüpfung, oder?
Die regexp würde sich auflösen in:
Code: (dl )
 $regexp = 'eins|drei|zwei';

Daraus folgt die Ersetzung:
Code: (dl )
$zeichen =~ s/(eins|drei|zwei)/$tausche{$1}/g;


Taugt für mich.

Gibt es eine Beschränkung für den Inhalt von $regexp? 255 Zeichen oder so?

Danke und Grüsse
moritz
 2008-09-09 12:04
#114403 #114403
User since
2007-05-11
923 Artikel
HausmeisterIn
[Homepage]
user image
Benutzer+2008-09-09 10:01:12--
Danke Moritz,

du baust indirekt eine ODER-Verknüpfung, oder?
Die regexp würde sich auflösen in:
Code: (dl )
 $regexp = 'eins|drei|zwei';


Richtig.

Quote
Gibt es eine Beschränkung für den Inhalt von $regexp? 255 Zeichen oder so?


Soweit ich weiss die Größe deines Arbeitsspeichers oder 2 (oder 4?) GB, je nachdem was kleiner ist. Für praktische Zwecke also eher nicht.
Benutzer
 2008-09-09 12:19
#114406 #114406
User since
2008-06-18
7 Artikel
BenutzerIn
[default_avatar]
Ich habe deinen Vorschlag in mein Skript eingebaut und festgestellt, dass einige Muster nicht eindeutig sind.

Beispiel:
Code: (dl )
1
2
3
4
5
%tausche = (
'eins' => 'zwei',
'zwei' => 'eins',
'drei' => 'vier');
$zeichen = 'bla eins bla zwei bla drei bla vier bla zweiundzwanzig';

Im Text zweiundzwanzig ist das Muster zwei enthalten und wird auch ersetzt. Soll aber nicht.

Die zu tauschenden Texte werden glücklicherweise entweder von "[Muster]" oder >[Muster]< umschlossen. Wie kriege ich das noch in die $regexp rein?
moritz
 2008-09-09 12:27
#114407 #114407
User since
2007-05-11
923 Artikel
HausmeisterIn
[Homepage]
user image
Also wenn du nur an Wortgrenzen ersetzen willst, kannst du \b benutzes:

Code: (dl )
s/\b($regex)\b/.../


Bei deinen anderen Begrenzern würde ich Lookarounds (?=...) und (?<=...) benutzen:

Code: (dl )
s/ (?<= [">] \[) ($regex) (?= \] ["<]) /.../x


(/x und Leerzeichen zu besseren Lesbarkeit der Regex).

Viel Spass beim Lesen von perlre ;-)
Benutzer
 2008-09-09 12:39
#114413 #114413
User since
2008-06-18
7 Artikel
BenutzerIn
[default_avatar]
Sorry, ich dachte die Wortgrenze funktioniert nicht in der Anwendung.
Falsche Annahme. Geht doch. Das war's.

perlre hab ich mehr als einmal konsultiert, aber ohne ausreichend Übung langt mein Abstraktionsvermögen nicht aus um alles zu begreifen. Ich bin einfach kein Programmierer und dazu Perl-Anfänger.

Vielen Dank für deine Hilfe.

Grüsse
pq
 2008-09-09 12:42
#114415 #114415
User since
2003-08-04
12208 Artikel
Admin1
[Homepage]
user image
Benutzer+2008-09-09 10:19:23--

Beispiel:
Code: (dl )
1
2
3
4
5
%tausche = (
'eins' => 'zwei',
'zwei' => 'eins',
'drei' => 'vier');
$zeichen = 'bla eins bla zwei bla drei bla vier bla zweiundzwanzig';

Im Text zweiundzwanzig ist das Muster zwei enthalten und wird auch ersetzt. Soll aber nicht.

dazu noch als anmerkung:
möchtest du tatsächlich 2 wörter ersetzen, von denen eines ein teilwort des anderen ist,
musst du die wörter vor dem bauen der regex noch nach länge sortieren. vergess ich auch
immer mal wieder. also
map { quotemeta $_ } sort { length $b <=> length $a } ...
damit wird immer das längste wort gematcht.
Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live. -- Damian Conway in "Perl Best Practices"
lesen: Wiki:Wie frage ich & perlintro Wiki:brian's Leitfaden für jedes Perl-Problem
Benutzer
 2008-09-09 12:53
#114418 #114418
User since
2008-06-18
7 Artikel
BenutzerIn
[default_avatar]
pq+2008-09-09 10:42:29--
dazu noch als anmerkung:
möchtest du tatsächlich 2 wörter ersetzen, von denen eines ein teilwort des anderen ist,
musst du die wörter vor dem bauen der regex noch nach länge sortieren. vergess ich auch
immer mal wieder. also
map { quotemeta $_ } sort { length $b <=> length $a } ...
damit wird immer das längste wort gematcht.


Gute Anmerkung, hoffentlich behalte ich sie für die Zukunft im Hinterstübchen.

In diesem besonderen Fall ging es um vollständige Wörter. Teilworte sollten nicht ersetzt werden. Das war Fehler Nummer 2. Siehe:
Benutzer+2008-09-09 10:19:23--
Im Text zweiundzwanzig ist das Muster zwei enthalten und wird auch ersetzt. Soll aber nicht.
<< >> 9 Einträge, 1 Seite



View all threads created 2008-09-09 11:02.