Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/322.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 正则表达式验证csv字符串_Java_Regex_Validation_Csv_Javafx - Fatal编程技术网

Java 正则表达式验证csv字符串

Java 正则表达式验证csv字符串,java,regex,validation,csv,javafx,Java,Regex,Validation,Csv,Javafx,我在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 基本上: 只有数字 第一组4或9位数字 如果第一组为9位->总共只有两组 如果第一组4位->总共三、四或五组 第二组和第三组数字1-9999 第四组和第五组

我在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
基本上:

  • 只有数字
  • 第一组4或9位数字
  • 如果第一组为9位->总共只有两组
  • 如果第一组4位->总共三、四或五组
  • 第二组和第三组数字1-9999
  • 第四组和第五组数字0-9999
现在将这些(有效)行中的一行视为一个“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);
这使我能够输入以下内容:

  • 以上所有有效行
  • 0101191010921011901093
  • 01011989765432121019109301094
如果我输入超过5个标识,它将正确地变为无效。 但如果我输入无效的标识01019 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");
            }
        }
    }
});
private final Predicate typingPredicate=new Predicate(){
@凌驾
公共布尔应用(字符串输入){
返回输入。匹配(模式);
}
};
textField.textProperty().addListener(新的ChangeListener()){
@凌驾

更改公众假期(ObservalEvalue这是您问题的解决方案。我对正则表达式做了一点修改。您的模式还以某种方式使最后一个无效语句有效,至少对我来说是这样。您遇到的基本问题是,您的正则表达式没有被括号包围。因此,您只需在最后一个语句a中添加
,?\\s
nd不是完整的正则表达式语句

这是我提出的一个改进的解决方案,它似乎验证了它应该做的一切

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());
}

我相信这个正则表达式可以满足您的所有要求:

^\d{9} [1-9]\d{0,3}$|^\d{4}(?: [1-9]\d{0,3}){2}(?: \d{1,4}){0,2}$

您可以试试。

您的regexp中的逗号是可选的这一事实允许“0101 9 1 1 1”被自由解析为两个或多个记录

要解决此问题,您可以要求它正好是一个标识或几个逗号分隔的标识:

final String pattern = String.format("(%s\\s*,\\s*){0,4}%s",base,base);

此外,我还建议base对您的输入规则更加严格,尽管它似乎与问题没有直接关系。

让我们来详细分析一下:

  • 仅限数字:

    正则表达式必须匹配数字和空格,并使用
    ^$
    仅匹配该数字和空格

  • 第一组4或9位数字:

    Straigh forward:
    \d{4}\d{9}

  • 如果第一组为9位->总共只有两组

    \d{9}\s\d
    9位数字组和第二位数字组

  • 如果第一组4位->总共三、四或五组

    \d{4}(\s\d){2,4}
    4位数字组,后跟2到4位数字组

  • 第二组和第三组数字1-9999

    1-9999->
    [1-9]\d{0,3}

  • 第四组和第五组数字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}))$
你可以试试看

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);
    }
}

我正在使用com.google.common.base.Predicate进行匹配。用匹配逻辑更新我的问题。为什么不:(I)用逗号分割文本(ii)检查每个标识是否与原始正则表达式有效,并且标识数是否少于6?Sry,最后两个组可以有0,updatet post。我注意到,如果第一个数字由9位数字组成,则第二个数字不在“数字1-9999”之后规则,我不确定它是否只适用于由4位数字组成的第一个数字后面的数字。@Aaron我也不知道,但我认为会是这样。我猜OP会说些什么。对于
987654321 11111111111
失败,因为您的
$
只与第二个数字(4位组)匹配。谢谢,这就是我所需要的!:)