Entwickler-Ecke

Programmiersprachen (Server) - Mehrere gleiche Zeichen hintereinander filtern


trm - Mi 05.06.13 21:37
Titel: Mehrere gleiche Zeichen hintereinander filtern
Huhu,

bevor ich mir jetzt eine eigene Function schreibe, gibt es für folgendes Problem eine Lösung?

Per Formular übertragener String ist z.B. ' aaaaaaaa '.

Da ich in einem Pflichtfeld aber nur ein a benötige und dies den Textfluss stören kann, wenn eine Zeichenfolge so ankommt (per E-Mail), würde ich das also auf ein Zeichen trimmen.

Gibt es für soeas schon eine fertige PHP-Lösung?


IhopeonlyReader - Mi 05.06.13 21:45


Quelltext
1:
2:
 if length(Text)>=1 then Zeichen := Text[1]
else Zeichen := '';

Wenn also der übergebene String (Text) länger(gleich)als 1 Zeichen ist, dann ist das Zeichen das erste Zeichen des Textes.


IhopeonlyReader - Mi 05.06.13 21:54

Und sonst, schau dir mal
http://php.net/manual/en/function.substr.php
an, hier wird erklärt, wie man per substr( Text, abZeichenNr, bisZeichenVorEnde) zeichen holt ;)


trm - Mi 05.06.13 22:16

Hi IhopeonlyReader,

leider am Thema vorbei.

Ich möchte nicht irgend einen String auf 1 Zeichen kürzen, sondern nur [n] Zeichen, welche gleichfolgend sind.

n = bliebiges Zeichen außer #32


IhopeonlyReader - Mi 05.06.13 22:33

und außer #0 denke ich ;)
Aber die Methode funktioniert doch trotzdem :D

Wenn du es "kompliziert" machen willst, erstelle ein Array of Byte(1..255) und gehst Zeichen für Zeichen durch und erhöhst das Array nur den Index [Ord(Zeichen)], endgültig setzt du das Zeichen mit der "höchsten wert" als DAS zeichen...

Aber da du ja nur ein Zeichen willst, und ja der ganze Text aus ein und demselben Zeichen besteht, kannst du einfach IRGENDein Zeichen aus dem String nehmen und es als DAS Zeichen verwenden

Quelltext
1:
 Zeichen := Text[1]                    

Dass es nicht "irgendein" string ist, sondern aus immer ein und demselben Zeichen besteht, ist dabei vollkommen egal !
Was stellst du dir denn vor? Es muss nuneinmal "in den String geschaut werden"


trm - Mi 05.06.13 23:45

Hm, entweder kann ich Deinen Antworten nicht folgen oder Du mir nicht oder aber, wir sind wirklich bei zwei verschiedenen Themen.

Woher soll ich denn wissen, was ein Benutzer mir als String zuwirft?

Ich kann doch nicht davon ausgehen, dass die Zeichenfolge wirklich aus ein und dem selben Zeichen in beliebiger Stringlänge besteht.

Wenn z.B. jemand in ein Inputfeld eingibt: aaaaaaaa ist das was anderes als wenn er eingibt: wwwwwwwwwww.de (gibt es wirklich)

Also nochmal: ich suchte eine fertige Lösung, die mir im Erfolgsfall ein True zurückgibt, wenn ein String komplett aus ein und dem selben Zeichen besteht.

Und danke für die Schleife, aber ich fragte wirklich - ach lies einen Satz über diesem ;)

Gruß Mathias


jfheins - Mi 05.06.13 23:52

Probiere mal soetwas:

PHP-Quelltext
1:
preg_replace('%(\w)\\1+%i''$1'$zeichenkette);                    

Das sollte zwei oder mehr Buchstaben, die aufeinanderfolgen, zu einem verkürzen. Wenn du das nur möchtest, falls der gesamte string ausschließlich aus den gleichen Buchstaben besteht, einfach noch der regex in ^$ klammern:

PHP-Quelltext
1:
preg_replace('%^(\w)\\1+$%i''$1'$zeichenkette);                    


trm - Do 06.06.13 00:24

Hallo jfheins,

die Varianten funktionieren perfekt für mein Vorhaben.

Jedoch habe ich noch eine Bitte.

Wie muss ich das erste Muster abändern, damit nicht ab 2, sondern z.B. erst ab 4 multiplen Zeichen eine entsprechende Anpassung vorgenommen wird?

Z.B. ist es ja üblich, http://www.blubblah.de anzugeben. Bei Deinem Tipp würde dann herauskommen: w.blublah.de -> zwei w und ein b fehlen.

Generell benötige ich zwar nur die zweite Möglichkeit, jedoch möchte ich gern dazu lernen und leider begreife ich die Suchmuster einfach nicht. Je länger die werden (siehe php.net - Beispiele), desto mehr komme ich durcheinander. Eine Übersicht (in deutsch für besseres Verständnis) der einzelnen Musterzeichen ( /, (, \, d+, .... ) wäre für mich ganz angenehm :D

Danke und liebe Grüße
Mathias


Edit:

Ich glaube, ich habe die Lösung gefunden ( http://www.tutorials.de/content/496-regulaere-ausdruecke-teil-2.html )

Mein Muster sollte mit %(\w)\\{4,}+%i funktionieren.

Danke für die Hilfe :)

Edit2:

Ha, zu früh gefreut. Funktioniert so nicht. Erklär bitte mal :)

Moderiert von user profile iconMartok: Selbstquoteeditfehler zusammengefasst


jfheins - Do 06.06.13 00:55

Tjaaaa ^^

(\w)\\1+ steht erstmal für (wortzeichen) gefolgt von einer backreference (also "das gleiche Zeichen von eben") und das dann eben 1 Mal oder öfter.

Du hast die 1 weggelassen, damit hast du nur noch einen Backslash gesucht und keine backreference mehr.... dein regex für 4 oder mehr Vorkommen lautet also %(\w)\\1{4,}%i ;-)

Übrigens eine tolle Seite zum testen: http://regexpal.com/
Dort besteht eine backreference aber nur aus einem backslash und der Zahl:, und es braucht auch keine Begrenazer mehr: (\w)\1{4,}


trm - Do 06.06.13 11:52

Huhu.

Danke für die Erklärung.
Somit kann ich gedanklich also das Muster wie folgt in Worten definieren:

%(\w)\\1{4,}+%i

% 1. Begenzer des Musters
( Start des Musters als kompletten String
\ Nachfolgendes Zeichen nicht als normales Charzeichen nutzen
w - keine Ahnung, aber ich tippe mal auf einen Typ, evlt. Widechar?
) Beenden des Strings als ganzes zu erkennen, d.h., das Muster ist hier zu Ende
\ wie oben
\ keine Ahnung, warum jetzt noch eine Escapezeichenmaskierung kommt
1 das ist aus Deiner Erklärung noch in Erinnerung ;)
{ hier startet ein Ausdruck
4 Aha, da ist die 4, mit der eine Art Initialwert festgelegt wird, also erst ab dem 5. identischen Zeichen in Folge wird das Muster angewandt
, Hm, ein Komma für eine weitere Abgrenzung
Nach dem Komma benötigen wir keinen Maximalwert der aufeinanderfolgenden Zeichen, somit fällt dieser Wert weg, könnte aber evtl. auch als -1 eingetragen werden
} Ende des Ausdrucks der Begrenzung
+ Das soll also eine Art Schleife sein, denke ich, mit der das Suchmuster an sich unendlich multipliziert wird (maximale Länge = Stringlänge)
% 2. Begrenzung des Musters und der Begrenzungen
i Klein/Großschreibungsoll nicht beachtet werden

Hm, ist das so in etwa richtig?

Gruß
Mathias :)


Martok - Do 06.06.13 12:21

() ist eine Gruppe. Auf eine Gruppe kannst du dann per Backreference (und auch in deinem Code, wenn du die Matches auswerten willst) zugreifen.
\w ist eine sogenannte Zeichenklasse, hier: word-character. Buchstaben, Zahlen und Unterstrich, alternativ könnte man also auch [a-zA-Z0-9_] schreiben.

{4,} bedeutet tatsächlich "mindestens 4, maximal unendlich". Das + dahinter erschließt sich mir grad nicht, mehr als Unendlich wirds doch nicht?

Schöne deutsche Übersicht: http://regexp-evaluator.de/tutorial/


jfheins - Do 06.06.13 13:29

user profile iconMartok hat folgendes geschrieben Zum zitierten Posting springen:
Das + dahinter erschließt sich mir grad nicht, mehr als Unendlich wirds doch nicht?

Ähh ja, das ist noch ein klitzekleiner Fehler :angel:

@trm: Deine Erklärung ist leider eher dürftig, da solltest du dich nochmal mit dem Aufbau von RegExen beschäftigen 8)

Damit PHP das Muster von den Optionen unterscheiden kann, wird es in Begrenzer eingefasst. Du kannst dafür vieles hernehmen - ich habe % benutzt, aber &, $, / oder # gehen auch.
Dann kommt eben eine Gruppe die ein word-char enthält. Die Backreference wird mit \\1 geschrieben, weil PHP sonst den Backslash verarbeitet. \\ wird durch PHP also mit einem einzigen \ ersetzt. Die RegEx Engine sieht also nicht \\1 sondern \1. Dahinter wird die Anzahl spezifiziert. (Das geht mit einem +, *, ? in kurz, oder eben mit den {} ausführlich)

Eine weitere Sache fällt mir aber gerade noch auf: Die 4 spezifiziert ja die Anzahl der Backreference. D.h. wenn du 4 Zeichen schon erkennen möchtest, dann hast su einen Match und drei Wiederholungen. Dein regex müsste also sein: (\w)\1{3,}
Bzw. für PHP: '%(\w)\\1{3,}%i'


trm - Do 06.06.13 17:25

Herzlichen Dank :)

@Martok, das schau ich mir mal an.
@jfheis: schön erklärt :)

Schöne Woche, bis bald.

Gruß Mathias


trm - Do 06.06.13 17:28

user profile icontrm hat folgendes geschrieben Zum zitierten Posting springen:
Herzlichen Dank :)

@Martok, das schau ich mir mal an.
@jfheis: schön erklärt :)

Schöne Woche, bis bald.

Gruß Mathias



Edit:

Hm, ist doch zum Heulen. Wenn ich nun noch Sonderzeichen mit verarbeiten möchte, muss ich die dann nach dem \w mit einfügen?
Z.B.: ein Sternchen ( * ) wäre ja eigentlich so aufzunehmen in die Gruppe: (\w*) oder?
Klappt aber nicht.


Sorry, ich klicke immer auf Bearbeiten mit Zitat. Wollte ich beide male nicht.


Marc. - Do 06.06.13 19:23

user profile icontrm hat folgendes geschrieben Zum zitierten Posting springen:
Hm, ist doch zum Heulen. Wenn ich nun noch Sonderzeichen mit verarbeiten möchte, muss ich die dann nach dem \w mit einfügen?

D.h. alle Zeichen, außer Zeilenumbrüche?


PHP-Quelltext
1:
preg_replace('%(.)\\1{3,}%i''$1'$zeichenkette);                    


Dafür gibt es den Dot ".", siehe auch http://www.regular-expressions.info/reference.html.


trm - Do 06.06.13 20:14

Dank Marc, das hatte ich auch schon gefunden. Mir ging es darum, einzelne Zeichen einzubinden, also zusätzlich zu \w
Also nicht alles, sondern ausgewählte Zeichen je nach Bedarf.

Gruß Mathias


Marc. - Do 06.06.13 20:20

user profile icontrm hat folgendes geschrieben Zum zitierten Posting springen:
Mir ging es darum, einzelne Zeichen einzubinden, also zusätzlich zu \w
Also nicht alles, sondern ausgewählte Zeichen je nach Bedarf.

Das hattest Du nicht geschrieben. :D

Dann probier's mal mit der Mengenschreibweise:

PHP-Quelltext
1:
preg_replace('%([av-])\\1{3,}%i''$1'$zeichenkette);                    

In diesem Fall werden a v und - berücksichtigt.

Siehe diesmal: http://www.ag-intra.net/linux-al-regex.html

Edit: Kommata entfernt.


trm - Do 06.06.13 20:55

Hm, also ist es gar nicht möglich in einer Gruppe, eine Syntax wie \w UND ausgesuchte Zeichen zu berücksichtigen?


Marc. - Do 06.06.13 21:06

user profile icontrm hat folgendes geschrieben Zum zitierten Posting springen:
Hm, also ist es gar nicht möglich in einer Gruppe, eine Syntax wie \w UND ausgesuchte Zeichen zu berücksichtigen?

Selbstverständlich. :nixweiss:

Ich hab hier [http://marc-henning.de/exp/regexp.php?input=aaaa****----333] kurz eine Testseite eingerichtet mit folgenden Zeilen:

PHP-Quelltext
1:
2:
3:
4:
5:
6:
7:
<?php
$zeichenkette = $_GET['input'];
printf("Eingebene Zeichenkette ist: %s \n"$zeichenkette);

$ausgabe = preg_replace('%([*,\w])\\1{3,}%i''$1'$zeichenkette);
printf("Ausgabe: %s \n"$ausgabe);
?>


trm - Do 06.06.13 21:51

Hi Marc,

also muss eine individuelle Auflistung der Zeichen vor dem \w stehen.

Das Komma wird aber hier auch als Gruppenzeichen gewertet ( http://marc-henning.de/exp/regexp.php?input=aaa***,,,,,,,,*----333 ), da es nicht maskiert ist, korrekt?

Vielen Dank, meine Fragen sind somit gelöst :)


Marc. - Do 06.06.13 22:32

user profile icontrm hat folgendes geschrieben Zum zitierten Posting springen:
Das Komma wird aber hier auch als Gruppenzeichen gewertet ( http://marc-henning.de/exp/regexp.php?input=aaa***,,,,,,,,*----333 ), da es nicht maskiert ist, korrekt?

Sorry, mein Fehler. :oops: Die Elemente der Menge werden hier nicht mit Kommata getrennt. Ich weiß auch gerade nicht, wie das mit Umlauten ist. Ich schaue morgen Abend noch einmal nach oder jemand anderes hilft dir in dieser Zeit.


trm - Fr 07.06.13 11:20

Danke, ist ja nicht eilig :)