Regex-Problem

C

Camino

Gast
Hallo,

bin mal wieder mit den Regex am verzweifeln. Und zwar möchte ich bei einem Textfeld mit DocumentFilter nur die Eingabemöglichkeit für Geldbeträge erreichen. Das Dezimaltrennzeichen soll nur ein Komma sein. Der Betrag soll maximal 6 Ziffern vor und maximal 2 nach dem Komma gestattet bekommen. Das Komma soll keinmal oder einmal erlaubt werden.

Bisher hatte ich als Regex-Pattern: [0-9,]+
Dadurch konnten aber mehrere Kommas eingegeben werden und auch mehr als 2 Nachkommastellen.

Meiner Vorstellung nach müsste das etwas Ähnliches wie das sein:
[0-9]{0,6},?[0-9]{0,2}
Also zuerst 0-6 Zahlen von 0-9, dann ein oder kein Komma und dann nochmal 0-2 Zahlen von 0-9. Vielleicht kann mir ja jemand erklären, was da falsch dran ist und wie es richtig heissen müsste.
 
Zuletzt bearbeitet von einem Moderator:

MrClave

Bekanntes Mitglied
Das hier sollte dein Problem lösen:
Code:
"^[\\d]{,6}[,]?[\\d]{,2}$"

Erlaubt 6 Vor, und 2 Nachkommastellen. Und halt ein, oder gar kein Komma.
Bin kein RegEx Profi, aber genau diesen RegEx Ausdruck habe ich schon erfolgreich angewandt.
 
C

Camino

Gast
Danke für die Antwort. Hab das mal getestet und folgende Fehlermeldung bekommen:

Java:
Exception occurred during event dispatching:
java.util.regex.PatternSyntaxException: Illegal repetition near index 4
^[\d]{,6}[,]?[\d]{,2}$
    ^

Wenn ich die Nullen mit in die Klammern schreibe
Java:
"^[\\d]{0,6}[,]?[\\d]{0,2}$"
dann kommt zwar keine Fehlermeldung, aber ich kann auch mehr Zeichen als 6 vor dem Komma eingeben.
 
Zuletzt bearbeitet von einem Moderator:
C

Camino

Gast
Hmm, seltsam. Hat bei mir keine Auswirkung. Ich kann auch mehrere Kommas eingeben, und auch mehr als 6 Ziffern vor und 2 hinter dem Komma.
 

Ark

Top Contributor
Probier mal
Code:
^[0-9]{,6}(?:,[0-9]{,2})?|(?:[0-9]{,6})?,[0-9]{,2}$
. Das dürfte deiner Spezifikation recht nahe kommen. Allerdings erlaubst du auch Strings wie "," oder ",0" oder "000,". Wahrscheinlicher suchst du also so was:
Code:
^(?:[1-9][0-9]{,5}|0)(?:,[0-9]{1,2})?$

Ach, ja: Ungetestet wie immer. :D

Ark
 
C

Camino

Gast
Ich hab das jetzt testweise mal so geschrieben
Java:
"(^[0-7]{0,6}[.,]?[0-2]{0,2}$)"
Nach meiner Logik müssten dann ja vor dem Komma nur max. 6 Ziffern von 0-7 und hinter dem Komma max. 2 Ziffern zwischen 0-2 eingegeben werden können. Ich kann aber vor dem Komma mehr als 6 Ziffern und hinter dem Komma auch mehr als 2 Ziffern (und diese auch zwischen 0-7) eingeben.
Regex ist mir echt ein Rätsel...
 
C

Camino

Gast
Probier mal
Code:
^[0-9]{,6}(?:,[0-9]{,2})?|(?:[0-9]{,6})?,[0-9]{,2}$
. Das dürfte deiner Spezifikation recht nahe kommen. Allerdings erlaubst du auch Strings wie "," oder ",0" oder "000,". Wahrscheinlicher suchst du also so was:
Code:
^(?:[1-9][0-9]{,5}|0)(?:,[0-9]{1,2})?$

Ach, ja: Ungetestet wie immer. :D

Ark

Schade, funktioniert immer noch nicht. Ich muss auch immer die Null in die geschweifte Klammer mit reinschreiben, sonst bekomme ich die oben genannte Exception.
 

Ark

Top Contributor
@Camino: Danke für den Hinweis wegen des Syntaxfehlers. (Den größtmöglichen Exponenten wegzulassen, scheint aber erlaubt zu sein. Irgendwie inkonsistent, finde ich. Na ja, egal.) Hab's gerade mal getestet, und spontan kann ich keinen Fehler erkennen:
Java:
public final class RegexTest{

	public static void main(String[] args){
		Pattern p=Pattern.compile("^(?:[1-9][0-9]{0,5}|0)(?:,[0-9]{1,2})?$");
		Matcher m = p.matcher("");
		System.out.println(m.reset("1,23").matches());
		System.out.println(m.reset("1,234").matches());
		System.out.println(m.reset("01,23").matches());
		System.out.println(m.reset("01,2").matches());
		System.out.println(m.reset("1,2").matches());
		System.out.println(m.reset("123400,").matches());
		System.out.println(m.reset("123400,0").matches());
		System.out.println(m.reset("123400,10").matches());
		System.out.println(m.reset("123400,100").matches());
		System.out.println(m.reset("987654,43").matches());
		System.out.println(m.reset("9876543,21").matches());
		System.out.println(m.reset("123,45,6").matches());
		System.out.println(m.reset(" 123,45 ").matches());
		System.out.println(m.reset(",12").matches());
		System.out.println(m.reset("12,").matches());
		System.out.println(m.reset("00,1").matches());
		System.out.println(m.reset("0,1").matches());
		System.out.println(m.reset("00,00").matches());
		System.out.println(m.reset("0,00").matches());
		System.out.println(m.reset("0,000").matches());
		System.out.println(m.reset(",").matches());
	}

}
Ausgabe:
Code:
true
false
false
false
true
false
true
true
false
true
false
false
false
false
false
false
true
false
true
false
false
Welcher Testfall ist denn falsch?

Ark
 
T

test1234567890

Gast
Das Komma-? ist falsch - ohne komma gehen 8 ziffern

eher sowas (erlaubt führende nullen + vor nach dem komma keine ziffern versionen:
"^(([0-9]{0,6})|([0-9]{0,6},[0-9]{0,2}))$"
bzw kann man dann noch die [1-9][0-9]{0,5} version verwenden, wenn man führende nullen nicht will.

Grüße
 
C

Camino

Gast
Sorry, musste erst mal den Rechner wechseln und das Projekt übertragen und noch diverse Sachen erledigen.

OK, so wie ich das sehe, liegt es vielleicht nicht unbedingt an dem Regex. Das mit den Tests sieht ja wirklich ok aus. Ich hab den Regex-Pattern halt in einer Klasse (abgeleitet von DocumentFilter), was ich bei einem Textfeld (bzw. dessen Document) gesetzt habe und als Parameter die maximale Zeichenanzahl und die Pattern-Art übergeben kann. Die Pattern selber sind in der DocumentFilter-Klasse als statische Variablen festgelegt.

Ich kann ja mal die Klasse mit dem DocumentFilter hier posten, vielleicht liegt ja da der Fehler...

Java:
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.DocumentFilter;

/**
 * Filter für Textfelder für bestimmte Zeichenlänge und Muster
 * @param maxChars maximal zulässige Zeichenlänge
 * @param pattern Muster für Texteingabe
 */
public class DocumentSizeFilter
extends DocumentFilter {
	
	// Pattern für Buchstaben, Sonderzeichen, Leerzeichen und Bindestrich
	public static final String FULLTEXT_PATTERN = "[ A-Za-z0-9-\\xC0-\\xFF]+";
	
	// Pattern für Buchstaben, Sonderzeichen, Leerzeichen und Bindestrich (A-Za-z0-9-_.@\\xC0-\\xFF)
	public static final String EMAIL_PATTERN = "[A-Za-z0-9.@!#$%&'*+-/=?^_`{|}~]+";
	
	// Pattern für Buchstaben, Sonderzeichen, Leerzeichen und Bindestrich
	public static final String TEXT_PATTERN = "[ A-Za-z-\\xC0-\\xFF]+";
	
	// Pattern nur für Buchstaben
	public static final String ONLY_TEXT_PATTERN = "[A-Za-z]+";
	
	// Pattern nur für Ziffern
	public static final String NUMBER_PATTERN = "[0-9]+";
	
	// Pattern für Dezimalzahlen mit Komma oder Punkt	
	public static final String DECIMAL_PATTERN = "[0-9.,]+";
	
	// Pattern für Geldbeträge/Währungen mit Komma	
	//public static final String CURRENCY_PATTERN = "[0-9,]+";
	//public static final String CURRENCY_PATTERN = "[0-9]+(,+)[0-9]{0,2}";
	//public static final String CURRENCY_PATTERN = "(^[\\d]{0,6}[.,]?[\\d]{0,2}$)";
	public static final String CURRENCY_PATTERN = "^(?:[1-9][0-9]{0,5}|0)(?:,[0-9]{1,2})?$";
	
	
	
	// Pattern für Datum (Zahlen und Punkt)	
	public static final String DATE_PATTERN = "[0-9.]+";


	private final int maxCharacters;
	private final String pattern;
	    

	public DocumentSizeFilter(final int maxChars, final String pattern) {
		maxCharacters = maxChars;
		this.pattern = pattern;
	}

	
	@Override
    public void replace(FilterBypass fb, int offs, int length, String str, AttributeSet a)
            throws BadLocationException {
		
        if (str.matches(pattern) && (fb.getDocument().getLength() + str.length() - length) <= maxCharacters || str.isEmpty()) {
            super.replace(fb, offs, length, str, a);
        }
        
    }

}

Die Pattern-Variable ist das CURRENCY_PATTERN. Im Textfeld wird der Filter so gesetzt:
Java:
((AbstractDocument) tfFonds.getDocument()).setDocumentFilter(new DocumentSizeFilter(9, DocumentSizeFilter.CURRENCY_PATTERN));

Bisher hat das mit den anderen Pattern eigentlich immer ganz gut geklappt.
 

Attila

Bekanntes Mitglied
Java:
public void replace(FilterBypass fb, int offs, int length, String str, AttributeSet a)
            throws BadLocationException {
    Document doc = fb.getDocument();
    String oldString = doc.getText(0,doc.getLength());
    String newString = oldString.substring(0, offs) + str + 
       (doc.getLength() > offs + length ? oldString.substring(offs+length) : "");       
    if ( newString.matches(pattern) || newString.isEmpty() ) {
        super.replace(fb, offs, length, str, a);
    }
}
 
Zuletzt bearbeitet:
T

test1234567890

Gast
Tip: Reservierte RegEx Zeichen musst Du escapen, und dazu gehört unter anderem auch der ".", falls du wirklich den Punkt meinst! (z.B. im Date Pattern nehme ich an, das du nicht IRGENDEIN Zeichen (= ".") erlauben willst). Gleiches gilt für Deine Sonderzeichen Pattern.
 
C

Camino

Gast
Tip: Reservierte RegEx Zeichen musst Du escapen, und dazu gehört unter anderem auch der ".", falls du wirklich den Punkt meinst! (z.B. im Date Pattern nehme ich an, das du nicht IRGENDEIN Zeichen (= ".") erlauben willst). Gleiches gilt für Deine Sonderzeichen Pattern.

Hmm, ich hab das gerade eben nochmal getestet. Bei meinem Pattern zum Datum kann ich tatsächlich nur Zahlen und Punkte eingeben, auch ohne Escapezeichen bei dem Punkt innerhalb der eckigen Klammer.
 
C

Camino

Gast
Vielleicht liegt's am ^$ drumrum? Also vielleicht nur diesen Ausdruck hier verwenden:
Code:
(?:[1-9][0-9]{0,5}|0)(?:,[0-9]{1,2})?
Das ist aber nur mal so geraten. :bahnhof:

Ark

Schade, leider nicht. Damit kann ich nur 9 Zahlen eingeben, aber kein Komma.

EDIT: Anscheinend hatte ich doch eher einen Fehler in meinem DocumentFilter. Wenn ich den geänderten Code von Attila übernehme, dann klappt es mit dem Pattern "(^[\\d]{0,6}[.,]?[\\d]{0,2}$)". Das einzige Problem ist, dass ich nur 8 Zahlen und nicht 9 (wie angegeben) eintippen kann.

Es wäre noch prima, wenn Attila mir noch erklären könnte, was in meiner alten Version des DocumentFilters falsch war.
 
Zuletzt bearbeitet von einem Moderator:

Ark

Top Contributor
@Camino: Jetzt sieht dein Regex so aus, als würden auch Strings wie "", ".", ",", "00.00", ",00", "0000,", "12345678" akzeptiert werden. oO

Ark
 
C

Camino

Gast
@Camino: Jetzt sieht dein Regex so aus, als würden auch Strings wie "", ".", ",", "00.00", ",00", "0000,", "12345678" akzeptiert werden. oO

Ark

Da hast du natürlich recht. ;( Na gut, den Punkt kann ich noch rausnehmen, so dass nur ein Komma akzeptiert wird. Das kommt meinem Wunschergebnis schon ziemlich nahe.

Wenn ich das von dir vorgeschlagene Pattern nehme "(?:[1-9][0-9]{0,5}|0)(?:,[0-9]{1,2})?" (ob mit oder ohne die Zeichen ^$), dann kann ich nur 6 Zahlen aber kein Komma eingeben.

Ich war schon am überlegen, ob ich nicht lieber ein JFormattedTextField nehmen sollte. Wobei mir das mit dem Pattern und DocumentFilter eigentlich besser gefällt. Mich würde ja aber auch mal interessieren, was bei meinem DocumentFilter falsch war.
 
Zuletzt bearbeitet von einem Moderator:

Ark

Top Contributor
Wenn ich das von dir vorgeschlagene Pattern nehme "(?:[1-9][0-9]{0,5}|0)(?:,[0-9]{1,2})?" (ob mit oder ohne die Zeichen ^$), dann kann ich nur 6 Zahlen aber kein Komma eingeben.
Doch, du kannst danach ein Komma (",") eingeben, aber nur, wenn danach noch eine oder zwei Ziffern (0 bis 9) kommen. Wenn du willst, dass auch Zahlen ohne Ziffern nach dem Komma akzeptiert werden (z.B. "1234,"), verwende "(?:[1-9][0-9]{0,5}|0)(?:,[0-9]{0,2})?". Oder ich verstehe das mit dem DocumentFilter nicht.

Ark
 
C

Camino

Gast
Doch, du kannst danach ein Komma (",") eingeben, aber nur, wenn danach noch eine oder zwei Ziffern (0 bis 9) kommen.

Stimmt, du hast recht, aber es geht nur, wenn ich mit dem Cursor wieder zurück gehe und dann das Komma setze. Es geht nicht, wenn ich z.B. 4 Zahlen schreibe und dann ein Komma setzen möchte.

Oder ich verstehe das mit dem DocumentFilter nicht.

Das Gefühl hab ich langsam bei mir, dass ich mich vielleicht nochmal mit der Funktionsweise des DocumentFilter näher beschäftigen sollte.
 

Ark

Top Contributor
Stimmt, du hast recht, aber es geht nur, wenn ich mit dem Cursor wieder zurück gehe und dann das Komma setze. Es geht nicht, wenn ich z.B. 4 Zahlen schreibe und dann ein Komma setzen möchte.
Dann wird wohl die Überprüfung quasi die ganze Zeit (d.h., gerade vor jeder Änderung) durchgeführt, und da "1234" erlaubt ist, aber "1234," nicht, kann man nach "1234" kein Komma eingeben.

Das heißt also, dass du entweder Strings wie "1234," erlauben (und eventuelle Nullen hinter dem Komma dir dazudenken bzw. im Nachhinein hinzufügen) musst, oder du sorgst dafür, dass die Korrektur/Überprüfung der Eingabe erst bei Verlassen des entsprechenden Textfelds durchgeführt wird.

Ark
 

Attila

Bekanntes Mitglied
Es wäre noch prima, wenn Attila mir noch erklären könnte, was in meiner alten Version des DocumentFilters falsch war.
Java:
public void replace(FilterBypass fb, int offs, int length, String str, AttributeSet a)
// String str <--- enthält nur die Änderungen, nicht den ganzen String
//...
// den ganzen Text zusammenfügen:
String newString = oldString.substring(0, offs) + str + 
       (doc.getLength() > offs + length ? oldString.substring(offs+length) : "");
 
C

Camino

Gast
Na ja, mit dem Pattern "(^[\\d]{0,6}[,]?[\\d]{0,2}$)" hat es ja fast schon so funktioniert, wie ich es gerne hätte. Die Ausnahmen ",", "00,00", ",00", "0000,", "12345678" kann ich ja versuchen, nach Verlassen des Textfeldes abzufangen. Die ersten 4 Möglichkeiten ergeben 00,00 und könnten einfach nicht akzeptiert werden. Beim letzten Fall "12345678" müsste ich überlegen, wie darauf reagiert wird. Es sollte auf jeden Fall auch die Möglichkeit geben, dass eine 6- oder weniger stellige Zahl ohne Nachkommastellen eingetragen werden kann. Vielleicht kann man auch mit einem Pattern verhindern, dass die Zahl mit einer Null anfängt oder vor dem Komma gar keine Ziffer steht.
 
C

Camino

Gast
Wenn du willst, dass auch Zahlen ohne Ziffern nach dem Komma akzeptiert werden (z.B. "1234,"), verwende "(?:[1-9][0-9]{0,5}|0)(?:,[0-9]{0,2})?".

Das scheint sogar noch die beste Variante zu sein. Da ist das einzige Problem wirklich das Komma ohne Nachkommastellen, was man ja einfach als ..,00 interpretieren könnte.
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
C Regex Problem Softwareentwicklung 1
TheJavaKid RegEx Problem Softwareentwicklung 2
B Regex-Problem mit replace außerhalb des matching bereichs liegender Zeichenketten Softwareentwicklung 2
TiME-SPLiNTER Banales regEx-Problem Softwareentwicklung 2
m@nu Problem mit einer RegEx Softwareentwicklung 4
M Regex-Regel um fehlende Schlusszeichen zu finden Softwareentwicklung 1
H Regex Frage Softwareentwicklung 2
H [Java]Regex Hilfe Softwareentwicklung 3
P Nur ganze Worte ersetzen mit RegEx Softwareentwicklung 2
G RegEx Version number Softwareentwicklung 8
M Regex Ausnahmen/Bedingungen Softwareentwicklung 5
H [RegEx] Anführungszeichen finden Softwareentwicklung 2
A Regex mit Negation Softwareentwicklung 2
ruutaiokwu regex, der mit nur html-comments, nicht aber javascript entfernt Softwareentwicklung 16
V RegEx um zu escapen? Softwareentwicklung 2
B Regex, um Sätze zu erkennen Softwareentwicklung 3
A Verschachteln von REGEX Softwareentwicklung 4
D Regex zur auswertung von SQL Statements Softwareentwicklung 3
S Regex Frage Softwareentwicklung 4
S sonderzeichen mit regex abfragen Softwareentwicklung 2
N Wie testet ihr regex auf korrektheit? Softwareentwicklung 8
S [RegEx] Dateigerecht geschriebene Namen parsen Softwareentwicklung 2
Z Analysemuster - Welches nehme ich für diese Problem? Softwareentwicklung 0
L Design Patterns zu abstraktem Problem Softwareentwicklung 2
C GIT Einstieg - Problem Softwareentwicklung 12
H Problem mit jsp:setproperty Softwareentwicklung 10
Landei MS-Access-Problem Softwareentwicklung 3
A 8 Damen Problem (Backtracking) Softwareentwicklung 2
U xmlvm-Problem: Der erzeugte Obj-C-Code erzeugt Fehler in Apple's Xcode SDK Softwareentwicklung 3
S Subversion und Source Folder Problem. Softwareentwicklung 6
G PHP Problem: Geltungsbereich von Variablen Softwareentwicklung 3
L Problem mit Vererbung Softwareentwicklung 6
C Ein Problem mit der RSA Versschlüsselung Softwareentwicklung 3
W Problem mit Umlauten in xml Dateien auf englischen Systemen Softwareentwicklung 7
H Problem Programmieren Softwareentwicklung 12
H Problem mit eclipse Softwareentwicklung 3
M IllegalStateException - Problem mit GUI und Observer pattern Softwareentwicklung 4
B JavaScript/JSON Problem Softwareentwicklung 2
MTiN Problem mit Rot/Schwarz-Baum Softwareentwicklung 1
F Problem mit DOS-Box Softwareentwicklung 2
A Problem mit Datum-Formatierung Softwareentwicklung 2
K Knapsack Problem: Algorithmus? Softwareentwicklung 7
M Traveling Salesman Problem Softwareentwicklung 6
S Problem PJIRC java-applet Softwareentwicklung 4
rambozola problem mit division in oracle Softwareentwicklung 2
Icewind Problem mit der OOP Softwareentwicklung 4
G Problem mit ActionListener Softwareentwicklung 7
C Mysql-Frage(Problem mit nicht durchgeführten Zugriff) Softwareentwicklung 5

Ähnliche Java Themen

Neue Themen


Oben