Regulární výraz, aby odpovídaly celé číslo doslovný

0

Otázka

Přemýšlel jsem o tom, rozebrat to seznam celých čísel (z majetku řetězec). Rád bych však jít nad rámec jen kladné a záporné desetinné hodnoty a analyzovat jakýkoli řetězec, který označuje Java literálu (JLS 17) , jak lze nalézt ve zdrojovém kódu. Podobně bych chtěl být shovívavý, pokud jde o jakékoli předpony, separátory a dodatky po celá čísla sami. Jinými slovy, chci najít je pomocí opakované výzvy k Matcher.find().

Je tam regulární výraz, který odpovídá na všechny možné Java celočíselné literály? Není třeba, aby podívejte se na horní a dolní meze.


I když jsem to udělal explicitně odkaz na JLS, ukážu některé platné a neplatné čísla:

  • -1: 1 je uzavřeno, ale mínus je unární operátor (budu upravte pokud je to nutné)
  • 0x00_00_00_0F: hodnota patnáct je uzavřeno jako hex číslice, podtržítko k oddělení dvou křupky
  • 0b0000_1111: hodnota patnáct v binární je uzavřeno
  • 017: osmičková hodnota patnáct je uzavřeno
integer java literals regex
2021-11-23 21:48:28
3

Nejlepší odpověď

4

Něco jako, že:

desetinné místo:
(?:0|[1-9](?:_*[0-9])*)[lL]?

hexadecimální:
0x[a-fA-F0-9](?:_*[a-fA-F0-9])*[lL]?

osmičkové:
0[0-7](?:_*[0-7])*[lL]?

binární:
0[bB][01](?:_*[01])*[lL]?

Všichni dohromady: (v freespacing režim)

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

vyzkoušet si to

2021-11-23 22:47:19

Ach, jo, to by se mi dlouhou cestu. Má to umožnit více podtrhuje? Možná, že ? by měla být *?
Maarten Bodewes

@MaartenBodewes: Jak jsem pochopil, doc, podtržítka nemají být contigous, ale možná jsem tomu špatně? (jinými slovy, je 1____1 dovolil ?). Všimněte si, že skupina, ve které volitelné podtržítko je, je nakonec opakovat.
Casimir et Hippolyte

Jo, může někdo přepsat ten regex? Zdálo se být schopni aktualizovat (testovací verze ještě měl ? místo *)....
Maarten Bodewes

Ještě jednou díky, napsal jsem odpověď , která analyzuje celé číslo i pomocí syntaxe regulárního výrazu se sídlem v duchu na své regex.
Maarten Bodewes
0

Po odpovědi od Kazimíra jsem se rozhodl vzít to trochu dále a provedeny některé kód, aby skutečně analyzovat celá čísla stejně, jsou uvedeny níže. To zahrnuje minus a plus symboly, i když ty jsou oficiálně není součástí literálu, jak je popsáno v JLS; jsou unární operátory.

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

Také jsem se snažil použít kód najít více celých čísel z řetězce, ale to nedopadlo dobře. Problém je, že některé neplatné znaky, jako například 0__0 přijali jako dva literály s hodnotou nula; není přesně to, co chcete. Takže prosím, používat regulární výrazy pouze ke zjištění, zda řetězec je vlastně číslo a oddělit celá čísla např. pomocí String.split(SEPARATOR_REGEX).

Legrační dost, moje Eclipse IDE to přijmout 0__0 jako doslovný, i když to oficiálně není kompatibilní s JLS. Ne v poho, ale divné none-the-méně.

2021-11-23 22:27:00

Rychle zobrazit vaše odpověď, omlouvám se, příliš unavený na to jít více do hloubky, ale: dávejte pozor, nepoužívat příliš mnoho zachycuje zejména pokud je nepotřebujeme. Použití non-zachycení skupiny (?:....) (zachycuje mají náklady).
Casimir et Hippolyte

Používám non-zachycení skupiny, pokud je to možné. Možná ověřit celé číslo, mohl bych odstranit pár; nepotřebuji je pro první zápas. Nebo možná bych mohl odstranit celý úvodní zápas a nechat smyčka, která ověřuje všechny možné formáty. Ale hele, nakonec jsme se snaží, aby odpovídaly celá čísla, ne stránky a stránky textu...
Maarten Bodewes
-1

No.... v nejjednodušší podmínky, o základu 2, 8, a 10 počet mohl použít stejný vzor, protože jejich hodnoty jsou všechny číselné znaky. ALE, pravděpodobně budete chtít výrazem pro každý typ. Problém je, že jste se dát jasně najevo svůj záměr. Jdu na předpokladu, že chceš výraz k ověření, co základny, konkrétní hodnota je.

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

Pro osmičkové a desítkové hodnoty, budete muset předřadit své vyjádření ke kontrole volitelný znak znak "^[\\+|-]?". Pro hex hodnoty, pokud očekáváte, že hodnoty se začínají "0x", já vám doporučuji předřadit výraz s těmi, doslovný hodnoty.

2021-12-09 23:34:58

Žádná podtržítka a to nemusí odpovídat skutečné celá čísla. A samozřejmě hranice (^$) nebude fungovat s najít, ale je to začátek...
Maarten Bodewes

@MaartenBodewes Děkuji. Uznávám, že ta podtržítka, ale to, co tím myslíš, že to nemusí odpovídat skutečné celá čísla? Také, nevěděla jsem, že hranice nefungují s find. Takže, děkuji vám za to, jak dobře.
hfontanez

Omlouvám se, moje chyba, myslel jsem, že to neodpovídá literály, jak je uvedeno v JLS, kde potřebujete mít 0x nebo 0X pro šestnáctkové soustavě atd.
Maarten Bodewes

@MaartenBodewes kromě toho, že jsem napsal " pokud očekáváte, že hodnoty se začínají "0x", já vám doporučuji předřadit výraz s těmi, doslovný hodnoty"
hfontanez

V jiných jazycích

Tato stránka je v jiných jazycích

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