Laden...

[gelöst] Regex findet Match an unerwarteten Stellen

Erstellt von martinO vor 13 Jahren Letzter Beitrag vor 13 Jahren 888 Views
M
martinO Themenstarter:in
164 Beiträge seit 2009
vor 13 Jahren
[gelöst] Regex findet Match an unerwarteten Stellen

Hallo zusammen

Wiedermal eine kleine Regex-Aufgabe, die mir zugetragen wurde. Ich verwende zusätzlich das Regex-Lab von herbivore (vielen Dank für das super Tool!!) aber ich sehe das Problem nicht.

Regex:

var tagRegex = new Regex(@"([^<>]*(<translate>[^<>]*</translate>))*", RegexOptions.Compiled);

Input: "<test>test text</test>"

if (tagRegex.IsMatch("<test>test text</test>"))
{
  return "gefunden";
}

Und da findet er mir immer was 😦 (das genaue problem: Wenn ein XML-Tag im Text vorkommt, dann darf nur "translate" drin stehen.. )

Weiss jemand Rat?

Merci

49.485 Beiträge seit 2005
vor 13 Jahren

Hallo martinO,

durch die Verwendung von * findest du auch Stellen, die Null-Zeichen lang sind. Und die gibt es in jedem Input-String, an jeder Stelle zwischen zwei Zeichen sowie vor dem ersten und nach dem letzten Zeichen, also bei einem String der Länge n sind es n+1 Stellen. Wobei dir Regex-Lab ja anzeigt, an welcher Stelle der Match gefunden wird und wie lang er ist.

Verwendet + statt *.

herbivore

M
martinO Themenstarter:in
164 Beiträge seit 2009
vor 13 Jahren

Hallo herbivore

Vielen Dank für die Antwort. Ich hab die Regex jetzt mit dem + angepasst.

var tagRegex = new Regex(@"([^<>]*(<translate>[^<>]*</translate>))+", RegexOptions.Compiled);

Nun findet er den "<test>text</test>" Input string nicht mehr, was auch gut ist. Jedoch findet er mir keinen string, der nur Zeichen entält ("hallo welt") - ist auch erlaubt.

var tagRegex = new Regex(@"([^<>]*|(<translate>[^<>]*</translate>))+", RegexOptions.Compiled);

Diese findet mir zwar "hallo welt", aber auch wieder "<test>text</test>" - wegen dem "|"... Ich switche schon länger zwischen zwei Unit Tests - mal funktioniert der eine, dann wieder der ander 😦

49.485 Beiträge seit 2005
vor 13 Jahren

Hallo martinO,

Diese findet mir zwar "hallo welt", aber auch wieder "<test>text</test>"

nö, er findet nicht "<test>text</test>", sondern er finden wieder einen leeren Match, weil du in dem entsprechenden Teilausdruck wieder * statt + verwendet hast.

Wenn du willst, dass der Pattern nur auf den gesamten Text passt und nicht auf Teile davon, verwende ^ und $.

herbivore

M
martinO Themenstarter:in
164 Beiträge seit 2009
vor 13 Jahren

Hallo herbivore

Vielen Dank für den Tipp mit dem $.

Für alle, die auf dieses Problem mal stossen:

Die Aufgabe: Ein Text darf XML Tags beinhalten. Wenn er XML Tags beinhaltet, dann einzig das translate-Tag.
Beispiele (aus meinen unit tests):
"Reiner Text" => gut
"prefix <translate>text</translate> suffix" => gut
"prefix <translate>text</translate>" => gut
"<translate>text</translate> suffix" => gut
"prefix <translate>text</translate><translate>text</translate> suffix" => gut
"prefix <translate>text</translate>asdf<translate>text</translate> suffix" => gut
"<a>a</a>" => nicht gut
"adf <b>a</b>" => nicht gut

Die Lösung:

            var tagRegex = new Regex(@"^[^<>]*([^<>]*(<translate>[^<>]*</translate>)[^<>]*)*$", RegexOptions.Compiled);

            if (tagRegex.IsMatch(this.value))
            {
                return "gut";
            }
      
            return "nicht gut";