Regulärer Ausdruck, der Umlaute und nicht Umlaute erfasst?

2 Antworten

Vom Beitragsersteller als hilfreich ausgezeichnet

Ein Vorschlag:

if (preg_match_all('/f([oö])t\1/ui', 'foto fötö bar bär', $matches)) {
	print_r($matches);
}

Ich habe Nadel und Heuhaufen einmal etwas verändert, da es für dich hilfreich sein könnte. Du kannst beim ersten Vorkommen deiner erwarteten Vokale eine Bereich festlegen:

[oöó]

diesen gruppieren:

([oöó])

und somit bei einem erneuten Vorkommen via back reference darauf verweisen:

\1

Dies verkürzt zumindest deinen regulären Ausdruck.


Babelfish 
Beitragsersteller
 21.03.2021, 13:10

Zeichenklassen hatte ich erst nicht verwendet, weil ich auch so was im Hinterkopf hatte:

(?:o|ö|oe|ó|ò|ô)

Allerdings macht das genau betrachtet keinen Sinn, da ich nach oe nur suchen müsste, wenn das auch im Suchtext vorkommt und dort sind die Zeichen ja immer richtig. Und wenn jemand mit oe sucht, wird es so oder so schwierig. Da hast du Recht, dass es mit Zeichenklassen etwas kürzer und übersichtlicher ist.

Eine Back-Referenz werde ich nicht brauchen, da ich beim Ersetzen ja nur was darum setzen muss. Ich werde es jetzt mal in dieser Art implementieren:

$str = 'foo föö bföo föos föo bar bär';
$result = preg_replace('/\b(f[oöóòô][oöóòô])\b/ui', '<b>$1</b>', $str);

Mal sehen, was da rauskommt.

Irgendwie hatte ich nur gehofft, dass es einen genauso einfachen Weg wie bei MySQL gibt.

0
regex9  21.03.2021, 13:21
@Babelfish

Den Ausdruck würde ich noch mit einem Quantifier abkürzen (falls du es noch nicht selbst bemerkt hast):

/\b(f[oöóòô]{2})\b/ui
0
Babelfish 
Beitragsersteller
 21.03.2021, 13:33
@regex9

Bei so einem manuellem Suchstring natürlich aber ich muss mir den ja vorher erst mal basteln. Der Nutzer kann bei der Suche bspw. entweder richtig „effectuée“ oder auch „effectuee“ eingeben. Mein Suchstring nach der Ersetzung mit einer Normalisierungs-Tabelle würde dann in etwa so aussehen:

'/\b([eéèêë]ff[eéèêë][cĉ]t[uüúùû][eéèêë][eéèêë])\b/ui'

Da macht der Quantifier den Kohl auch nicht fett und ist auch nicht so einfach zu implementieren.

0
in MySQL ist das bei der Suche kein Problem, da kann man mit COLLATE utf8_general_ci genau das erreichen.

In PHP gibt's dafür

iconv("utf-8","ascii//TRANSLIT",$suchbegriff);

https://www.php.net/manual/en/function.iconv.php

Alex


Babelfish 
Beitragsersteller
 22.03.2021, 13:22

Ok, aber wie hilft mir das bei meinem Problem weiter? Ich bekomme hier bspw. folgende Ausgabe:

$str = 'Passé composé französisch';

echo iconv("utf-8", "ascii//TRANSLIT", $str);

// Pass'e compos'e franz"osisch

Ich sehe jetzt auf Anhieb nicht, wie ich damit in dem Text „Passé composé französisch“ das Wort „composé“ markieren kann, wenn nach „compose“ gesucht wurde.

0
EinAlexander  23.03.2021, 09:51
@Babelfish
Ich sehe jetzt auf Anhieb nicht, wie ich damit in dem Text „Passé composé französisch“ das Wort „composé“ markieren kann, wenn nach „compose“ gesucht wurde.

Mit iconv bringst Du needle (also den Suchbegriff) und haystack (der Text, der durchsucht wird) ins gleiche Format. Das kannst Du dann vergleichen. Aus

Passé composé französisch

wird damit

Pass'e compos'e franz"osisch

Und durch das Ignorieren sämtlicher ' sowie '' bleibt als haystack übrig:

Passe compose franzosisch

Und damit kannst Du die Stelle finden, an der das Wort compose vorkommt.

0
Babelfish 
Beitragsersteller
 23.03.2021, 10:00
@EinAlexander

Das funktioniert in meinen Fall aber leider nicht, da ich den gefundenen Text ja auch wieder anzeigen will und dort dann auch der Originaltext stehen soll. Auf der Webseite steht also bspw.:

Das Passé composé entspricht dem deutschen Perfekt.

Der Nutzer sucht nach „passe compose“. Danach soll der Text so markiert sein:

Das Passé composé entspricht dem deutschen Perfekt.

Das geht halt nicht, wenn ich auch den Originaltext vor dem Suchen schon ändere.

0
EinAlexander  23.03.2021, 10:09
@Babelfish
Das funktioniert in meinen Fall aber leider nicht, da ich den gefundenen Text ja auch wieder anzeigen will und dort dann auch der Originaltext stehen soll.

Du sollst nicht die Anzeige des Textes konvertieren sondern nur den haystack, der durchsucht wird. Der gesamte Text steht in der Variablen $original. Daraus machst Du

$haystack = iconv("utf-8", "ascii//TRANSLIT", $original);

und entfernst die einfachen und doppelten Anführungszeichen. Der Suchbegriff steht in der Variablen $suchbegriff. Daraus machst Du

$needle = iconv("utf-8", "ascii//TRANSLIT", $suchbegriff);

und entfernst auch hier die einfachen und doppelten Anführungszeichen.

Jetzt kannst Du $haystack nach den Vorkommen von $needle durchsuchen. Den zurückgegebenen (zweites und drittes Wort) kannst Du dann dazu verwenden, die entsprechende Stelle (=zweites und drittes Wort) in $original mit <strong> zu markieren.

Prinzip klar?

0
Babelfish 
Beitragsersteller
 23.03.2021, 11:39
@EinAlexander
Den zurückgegebenen (zweites und drittes Wort) kannst Du dann dazu verwenden, die entsprechende Stelle (=zweites und drittes Wort) in $original mit <strong> zu markieren.

Da bin ich doch genau wieder am Anfang meines Problems angelangt.

Nach der Variante habe ich dann:

$haystack → 'Das Passe compose entspricht dem deutschen Perfekt.'

$needle → 'passe compose'

In $haystack finde ich dann natürlich $needle, soweit klar. Nur wie soll ich dieses Ergebnis dann nutzen, um in $original das zu bekommen:

Das <b>Passé composé</b> entspricht dem deutschen Perfekt.

Die Umwandlung mit iconv hilft mir ja nur um überhaupt zu testen, ob der Begriff darin vorkommt. Damit habe ich aber noch nicht den Originaltext geändert.

Prinzip klar?

Leider noch nicht.

0
EinAlexander  23.03.2021, 12:29
@Babelfish
In $haystack finde ich dann natürlich $needle, soweit klar.

Und damit hast Du die Positionen innerhalb des Strings $original, an denen der Suchbegriff beginnt und endet, und Du kannst die entsprechenden Leerzeichen des Strings $origninal durch das öffnende <b>-Tag bzw das schließende </b>-Tag ersetzen.

In Deinem Beispiel wäre das

  • ersetze das vierte character durch '[SPACE]<b>'
  • ersetze das achtzehnte character durch '</b>[SPACE]'
0
Babelfish 
Beitragsersteller
 23.03.2021, 13:11
@EinAlexander

Leider funktioniert das eben nicht, da zum Beispiel ß zu ss ersetzt wird und dann zwei statt einem Buchstaben drin sind und $haystack und $original eine andere Länge haben. Auch andere Sonderzeichen wie œ oder æ werden mit zwei Zeichen ersetzt.

Aus „Lerne fleißig Passé composé…“ wird dann eben „Lerne fleissig Passe compose…“ und dann klappt die Ersetzung nicht an diesen Positionen.

0
EinAlexander  23.03.2021, 14:41
@Babelfish
und dann klappt die Ersetzung nicht an diesen Positionen.

dann nimm halt die Position sondern zähle die Leerzeichen.

Aus „Lerne fleißig Passé composé…“ wird dann eben „Lerne fleissig Passe compose…“

Dann ersetzt man das zweite Leerzeichen im String durch [SPACE]<b> und das dritte Leerzeichen im String durch </b>[SPACE]

0
Babelfish 
Beitragsersteller
 23.03.2021, 15:35
@EinAlexander

Leerzeichen zählen ist zu unsicher, da es viele Varianten mit Klammern, Satzzeichen oder Zeilenumbrüchen geben kann, die dann alle mit gezählt werden müssen:

Lerne fleißig: Présente (aber auch Passé récent/composé)
unregelmäßigen Verben im:
* Passé composé
* Passé simple

Ich haben keinen Einfluss auf den Originaltext und da kann alles drin stehen.

Ich denke nicht, dass ich so direkt zum Ziel komme. Allerdings hilft mir iconv mal beim Normalisieren des Suchstrings. Danke! Mit dem normalisierten String werden ich dann mittels Regulären Ausdruck wie mit regex9 besprochen die Ersetzung vornehmen.

0