我在javaFX中有一个TextField,其中背景颜色相应地改变,如果内容有效。
有效:
987654321 1
987654321 21
0101 9 1
1701 91 1 2
4101 917 1 0 43
0801 9 178 2 0
0111 9 1 084 0
无效:
0101 9 1 0 1 0
3124
0314 9
基本上:
现在将其中一条(有效)行视为一个“Ident”。
目前的正则表达式是:
final String base = "(\\d+\\s+\\d+)|(\\d+\\s+\\d+\\s+\\d+(\\s+\\d+)?(\\s+\\d+)?)|(\\d+\\s+\\d+\\s+\\d+)|(\\d+\\s+\\d+\\s+\\d+\\s+\\d+)|(\\d+\\s+\\d+\\s+\\d+\\s+\\d+\\s+\\d+)";
到目前为止效果很好,但现在我想要包含csv。所以我只能输入一个我以前使用的标识,或者用逗号(,)分隔的多个标识符,但总共不超过五个标识符。
我的尝试:
final String pattern = String.format("(%s,?\\s*){1,5}",base);
这使我可以输入:
如果我输入5个以上的标识,它就会无效。 但是如果我输入无效的身份0101 9 1 1 1 1 1 1 1 1它仍然有效。
有什么建议吗? :)
编辑:这是匹配逻辑:
private final Predicate<String> typingPredicate = new Predicate<String>() {
@Override
public boolean apply(String input) {
return input.matches(pattern);
}
};
textField.textProperty().addListener(new ChangeListener<String>() {
@Override
public void changed(ObservableValue<? extends String> observableValue, String previous, String current) {
if (current != null) {
if (StringUtils.isEmpty(current) || typingPredicate.apply(current.trim())) {
textField.getStyleClass().removeAll("invalid");
} else {
textField.getStyleClass().add("invalid");
}
}
}
});
答案 0 :(得分:3)
你的正则表达式中的逗号是可选,这个事实允许“0101 9 1 1 1 1 1 1 1 1 1”被自由解析为两个或多个记录。
要解决此问题,您可以要求它只是一个或几个逗号分隔的:
final String pattern = String.format("(%s\\s*,\\s*){0,4}%s",base,base);
另外,我建议将 base 本身的输入规则更严格,尽管它似乎与问题没有直接关系。
答案 1 :(得分:1)
这是您问题的解决方案。我稍微修改了正则表达式。你的模式也以某种方式使无效语句的最后一个有效,至少对我而言。您遇到的基本问题是,您的正则表达式未被括号括起来。所以你只是将,?\\s
添加到最后一个语句而不是完整的正则表达式语句。
这是我提出的一个经过修改的解决方案,似乎可以验证应该做的所有事情。
public static void main(String[] args) {
String[] inputs = {"987654321 1",
"987654321 21",
"0101 9 1",
"1701 91 1 2",
"4101 917 1 0 43",
"0801 9 178 2 0",
"0111 9 1 084 0",
"0101 9 1 0 1 0",
"3124",
"0314 9"};
String regex = "(((\\d{9}(\\s\\d*)))|(\\d{4}(\\s[1-9]\\d{0,3}){2}(\\s\\d{1,4}){0,2}))";
String csvRegex = "("+ regex + ",\\s){0,4}"+regex;
for(String s : inputs) {
Matcher m = Pattern.compile(csvRegex).matcher(s);
System.out.println(m.matches());
}
String falseCSVString = "987654321 1, 987654321 21, 1701 91 1 2, 0111 9 1 084 0, 0101 9 1 1 1 1 1 1 1 1 1";
Matcher m = Pattern.compile(csvRegex).matcher(falseCSVString);
System.out.println(m.matches());
String rightCSVString = "987654321 1, 987654321 21, 1701 91 1 2, 0111 9 1 084 0, 0101 9 1";
m = Pattern.compile(csvRegex).matcher(rightCSVString);
System.out.println(m.matches());
}
答案 2 :(得分:1)
答案 3 :(得分:1)
让我们分解一下:
仅限数字:
正则表达式必须匹配数字和空格,并使用^$
仅匹配
第一组4或9位数:
直线前进:\d{4}|\d{9}
如果第一组9位 - &gt;总共只有两组
\d{9}\s\d
9位数组和第二个
如果第一组4位数 - >总共三,四,五组
\d{4}(\s\d){2,4}
4位数组后跟2到4组
第2组和第3组1-9999
1-9999 - &gt; [1-9]\d{0,3}
第4组和第5组0-9999
轻松一个...... \d{1,4}
然后结合一切:
^ # match start of string
(\d{4} # group start with 4 digits
(\s[1-9]\d{0,3}){2} # group of 1-9999 twice
(\s\d{1,4}){0,2} # group of 0-9999 zero to two times
)|(\d{9} # group start with 9 digits
\s[1-9]\d{0,3} # group of 1-9999
)$ # end of string match
给出了:
^((\d{4}(\s[1-9]\d{0,3}){2}(\s\d{1,4}){0,2})|(\d{9}\s[1-9]\d{0,3}))$
您可以尝试live here
答案 4 :(得分:1)
尝试
String ident = "\\s*(([0-9]{9}\\s+[1-9][0-9]{0,3})|(\\d{4}(\\s+[1-9]\\d{0,3}){2}(\\s+\\d{1,4}){2}))\\s*";
String regex = String.format("\\A%s(,%s){0,4}\\z", ident, ident);
SSCCE:
import java.util.regex.Pattern;
import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.beans.binding.BooleanBinding;
import javafx.scene.Scene;
import javafx.scene.control.TextField;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class ValidatingTextFieldExample extends Application {
private BooleanBinding valid ;
@Override
public void start(Stage primaryStage) {
String ident = "\\s*(([0-9]{9}\\s+[1-9][0-9]{0,3})|(\\d{4}(\\s+[1-9]\\d{0,3}){2}(\\s+\\d{1,4}){2}))\\s*";
String regex = String.format("\\A%s(,%s)*\\z", ident, ident);
Pattern pattern = Pattern.compile(regex);
TextField textField = new TextField();
String INVALID_STYLE = "-fx-background-color: red;" ;
textField.setStyle(INVALID_STYLE);
valid = Bindings.createBooleanBinding(() ->
pattern.matcher(textField.getText()).matches(),
textField.textProperty());
valid.addListener((obs, wasValid, isValid) -> {
if (isValid) {
textField.setStyle("");
} else {
textField.setStyle(INVALID_STYLE);
}
});
StackPane root = new StackPane(textField);
primaryStage.setScene(new Scene(root, 350, 120));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}