经常表达相匹配整数字

0

的问题

我在想关于分析清单的整数(从一个酒店string)。 然而,我想要超越仅仅是积极的和消极小数值,并分析 任何 串的指示 Java整数字(捷尔思17) 为可以找到源代码。 同样,我想要宽容有关的任何前,分离和附录周围的整自己。 换句话说,我要找到他们用重复调用 Matcher.find().

是否有一个定期表达相匹配的所有可能的Java整数文字? 它不需要检查的上限和下限的。


虽然我做了明确的链接捷尔思,我会展示一些有效和无效的数字:

  • -11 是匹配,但减去是一元的操作者(我会调整如果需要的话)
  • 0x00_00_00_0F值十五匹配作为进制数字,下划线分开的两半
  • 0b0000_1111价值五十二元匹配
  • 017:八值的十五匹配
integer java literals regex
2021-11-23 21:48:28
3

最好的答案

4

类似的东西:

decimal:
(?:0|[1-9](?:_*[0-9])*)[lL]?

hexadecimal:
0x[a-fA-F0-9](?:_*[a-fA-F0-9])*[lL]?

octal:
0[0-7](?:_*[0-7])*[lL]?

二进制:
0[bB][01](?:_*[01])*[lL]?

所有的在一起:(在freespacing模式)

(?:
    0
    (?:
        x [a-fA-F0-9] (?: _* [a-fA-F0-9] )*
      |
        [0-7] (?: _* [0-7] )*
      |
        [bB] [01] (?: _* [01] )*
    )?
  |
    [1-9] (?: _* [0-9] )*
)
[lL]?

测试它

2021-11-23 22:47:19

啊,是啊,那会给我一段很长的路要走。 它不会允许多次强调了吗? 也许这 ? 应该是一个 *?
Maarten Bodewes

@MaartenBodewes:我的理解的文件,强调不应该contigous,但也许我错了吗? (换句话说是 1____1 允许?). 请注意,集团内部其《任择强调的是,最终还是重复的。
Casimir et Hippolyte

嗯,任何人都可以改写,regex? 我似乎能够更新(测试版本仍然有? 而不是*)....
Maarten Bodewes

再次谢谢你,我发表 一个答案 ,分析整数以及使用经常表达的语法基于在精神上你的regex.
Maarten Bodewes
0

以后的答复从卡西米尔我决定采取这一点进一步和实施一些代码实际上分析整数,包括如下。 它包括减和加符号,尽管这些都是正式不一部分的整数文本中所描述的捷尔思的;它们是一元的运营商。

package nl.owlstead.ifprops;

import java.math.BigInteger;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public final class JavaIntegerParser {
    private static final Pattern BINARY = Pattern.compile("(0b)([01](?:_*[01])*)(L?)", Pattern.CASE_INSENSITIVE);
    private static final Pattern OCTAL = Pattern.compile("(0)([0-7](?:_*[0-7])*)(L?)", Pattern.CASE_INSENSITIVE);
    private static final Pattern DECIMAL = Pattern.compile("()(0|(?:[1-9](?:_*[0-9])*))(L?)", Pattern.CASE_INSENSITIVE);
    private static final Pattern HEXADECIMAL = Pattern.compile("(0x)([0-9a-f](?:_*[0-9a-f])*)(L?)", Pattern.CASE_INSENSITIVE);
   
    // NOTE: OCTAL should be before DECIMAL if this is used to find the pattern
    private static final Pattern SIGNED_INTEGER_LITERAL = Pattern.compile(
            "(?:([+-])\\s*)?(" + 
            BINARY + "|" + OCTAL + "|" + DECIMAL + "|" + HEXADECIMAL + 
            ")", Pattern.CASE_INSENSITIVE);
        
    public static int parseJavaInteger(String javaInteger) throws NumberFormatException {
        BigInteger value = parseIntegerAsBigInt(javaInteger);
        try {
            return value.intValueExact();
        } catch (@SuppressWarnings("unused") ArithmeticException e) {
            throw new NumberFormatException("Number is not between Integer.MIN_VALUE and Integer.MAX_VALUE");
        }
    }
    
    public static long parseJavaLong(String javaLong) throws NumberFormatException {
        BigInteger value = parseIntegerAsBigInt(javaLong);
        try {
            return value.longValueExact();
        } catch (@SuppressWarnings("unused") ArithmeticException e) {
            throw new NumberFormatException("Number is not between Integer.MIN_VALUE and Integer.MAX_VALUE");
        }
    }

    private static BigInteger parseIntegerAsBigInt(String javaLiteral) {
        Matcher intMatcher = SIGNED_INTEGER_LITERAL.matcher(javaLiteral);
        if (!intMatcher.matches()) {
            throw new NumberFormatException(javaLiteral + " is not recognized as a Java integer literal");
        }
        
        String signGroup = intMatcher.group(1);
        String prefixAndValueGroup = intMatcher.group(2);
        String radixGroup = "";
        String valueGroup = "";
        // String longGroup = "";
        List<Pattern> patterns = List.of(BINARY, OCTAL, DECIMAL, HEXADECIMAL);
        for (Pattern pattern : patterns) {
            Matcher specificMatcher = pattern.matcher(prefixAndValueGroup);
            if (specificMatcher.matches()) {
                radixGroup = specificMatcher.group(1);
                valueGroup = specificMatcher.group(2);
                // longGroup = specificMatcher.group(3);
                break;
            }
        }
        
        if (valueGroup == null) {
            throw new RuntimeException("Number both matches but doesn't contain a value (parser error)");
        }

        BigInteger sign = signGroup != null && signGroup.matches("-") ? BigInteger.ONE.negate() : BigInteger.ONE; 
        
        int radix;
        switch (radixGroup.toLowerCase()) {
        case "0b":
            radix = 2;
            break;
        case "0":
            radix = 8;
            break;
        case "":
            radix = 10;
            break;
        case "0x":
            radix = 16;
            break;
        default:
            throw new RuntimeException();
        }
 
        BigInteger value = new BigInteger(valueGroup.replaceAll("_", ""), radix).multiply(sign);
        return value;
    }
}

我还试图利用的代码,以找到多个整数从一串,但这并不顺利。 问题是,一些无效的文本,例如 0__0 得接受为两个文本的价值为零;不正是你想要的。 所以请使用regex只有检测,如果一串实际上是一个整数和单独的整数,例如使用 String.split(SEPARATOR_REGEX).

有趣的是我蚀IDE没有接受 0__0 作为一个文本,即使它是正式不符合捷尔思. 不大,但古怪的无--更少。

2021-11-23 22:27:00

快看你的答案,对不起太累了去更加深刻,但是:照顾到不使用太多的捕获特别是如果不需要他们。 使用非捕获团 (?:....) (捕获具有成本)。
Casimir et Hippolyte

我不要使用非捕获团体在可能的情况。 也许验证整个整数我可以删除一些,我不需要他们最初的匹配。 或者,也许我可以删除整个初始比赛和刚刚离开的循环,验证所有可能的格式。 但是,嘿,在结束我们在试着匹配整数,不一页又一页的文字...
Maarten Bodewes
-1

。 在最简单的条款,基2、8和10号码 可以 使用相同的模式,因为他们的价值是所有的数字。 但是,你可能希望表达对于每一个类型。 问题是,你并没有弄清楚你的意图。 我会假设你想表达以验证什么基础的一个特别的价值。

String base10Regex = "[0-9]+";
String base2Regex = "[0-1]+";
String base8Regex = "[0-7]+";
String base16Regex = "^[0-9A-F]+$";

对八和小数值,则将需要在前面加上你的表达检查的一个可选的签字 "^[\\+|-]?". 为hex值,如果你期待的价值观开始的"0x",我将建议预先准备的表达,与那些文本的价值观。

2021-12-09 23:34:58

没有下划线和不相匹配的实际整数。 当然,边界(^$)不会与现,但它是一个开始...
Maarten Bodewes

@MaartenBodewes谢谢你。 我授予你的强调,但是你是什么意思这不符合实际整数? 还有,我不知道边界不起作用 find. 所以,谢谢你对这一点为好。
hfontanez

对不起,我的错,我的意思是,它不匹配的文字作为指示在捷尔思,你需要的 0x0X 对于十六等。
Maarten Bodewes

@MaartenBodewes除了我写的"如果您期望值的开始"0x",我将建议预先准备的表达,与那些文本价值观"
hfontanez

其他语言

此页面有其他语言版本

Русский
..................................................................................................................
Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................