Regulárny výraz na zápas integer doslovný

0

Otázka

Premýšľal som o analýze zoznam celé čísla (z vlastníctva string). Avšak, ja by som chcel ísť ďalej, ako je len kladné a záporné desatinné hodnoty a analyzovať akýkoľvek reťazec, ktorý označuje, Java celé doslovné (JLS 17) , ako možno nájsť v zdrojovom kóde. Podobne, by som chcel byť lenient s ohľadom na všetky predpony, odlučovače a dodatky okolo čísla seba. Inými slovami, chcem nájsť ich pomocou opakovaných výziev na Matcher.find().

Existuje regulárny výraz, ktorý zahrnie všetky možné Java integer literály? Nie je potrebné skontrolovať, hornej a dolnej hranice.


Aj keď som si výslovne odkaz na JLS, ukážem niektoré platné a neplatné čísla:

  • -1: o 1 je uzavreté, ale mínus je unárne operátora (budem upraviť, ak je to potrebné)
  • 0x00_00_00_0F: hodnota pätnásť zhodný ako hexadecimálne číslice, podčiarkovník oddeliť dve chrumky
  • 0b0000_1111: hodnota pätnásť v binárnych je zhodné
  • 017: o octal hodnota pätnásť je zhodné
integer java literals regex
2021-11-23 21:48:28
3

Najlepšiu odpoveď

4

Niečo také, že:

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

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

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

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

Všetky spolu: (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]?

otestujte sa

2021-11-23 22:47:19

Ach, áno, že by si ma dlhá cesta. Neumožňuje viac podčiarkuje aj keď? Možno, že ? by mal byť *?
Maarten Bodewes

@MaartenBodewes: Ako som pochopil doc, podčiarkuje nie ste mali contigous, ale snáď sa mi madam zle? (inými slovami, je 1____1 povolené ?). Všimnite si, že vo vnútri skupiny, ktoré voliteľné podčiarknutia je, je nakoniec sa opakuje.
Casimir et Hippolyte

Huh, môže niekto prepísať, že regulárny výraz? I zdalo byť schopný aktualizovať (testovacia verzia stále mal ? namiesto *)....
Maarten Bodewes

Ešte raz vďaka, som vyslaný odpoveď , že analyzuje celé číslo, ako aj pomocou regulárneho výrazu syntax založené v duchu na váš regulárny výraz.
Maarten Bodewes
0

Po odpovedi od Casimirovho som sa rozhodol vziať to trochu ďalej a implementované niektoré kód skutočne analyzovať celé čísla, rovnako,, ktorý uvádzame nižšie. Nezahŕňa mínus a plus symboly, aj keď sú oficiálne nie je súčasťou celé doslovné, ako je popísané v JLS; sú unárne 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;
    }
}

Tiež som sa snažil použiť kód nájsť viac číslami od reťazec, ale že nemal ísť dobre. Problém je, že niektoré nesprávne literály ako 0__0 bol prijatý ako dva literály s hodnotou nula; nie je to presne to, čo chcete. Takže prosím, použite regulárny výraz, len ak chcete zistiť, či reťazec je vlastne celé číslo a oddeľte čísla, napr. pomocou String.split(SEPARATOR_REGEX).

Vtipné dosť moje Eclipse IDE si prijímať 0__0 ako doslovný, aj keď je oficiálne nie sú v súlade s JLS. Nie biggy, ale divné žiadna--menej.

2021-11-23 22:27:00

Rýchlo zobraziť vašu odpoveď, ospravedlňujeme sa príliš unavený na to ísť viac hlboké, ale: starať sa nemali používať príliš veľa zachytáva najmä ak nepotrebuješ. Použitie non-zachytenie skupiny (?:....) (zachytáva obstarávacia cena).
Casimir et Hippolyte

Ja použitie non-zachytenie skupín, kde je to možné. Možno overiť celý integer som mohol odstrániť pár; nepotrebujem ich na pôvodnú zápas. Alebo možno by som mohol odstrániť celý počiatočnej zhody a nechaj slučky, ktorá overí všetky možné formáty. Ale hej, v závere sa snažíme, aby sa zápas celé, nie stránok a stránok textu...
Maarten Bodewes
-1

No.... v najjednoduchšie pojmy, základne, 2, 8, a 10 počet by mohol použiť rovnaký vzor, pretože ich hodnoty sú všetky číselné znaky. ALE, pravdepodobne budete chcieť výraz pre každý typ. Problém je, že vám nie je jasné váš zámer. Ja sa chystám na predpoklade, že budete chcieť termín na overenie, čo base určitú hodnotu.

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

Pre octal a desatinné hodnoty, ktoré budete potrebovať, napíš pred svojho prejavu na kontrolu voliteľný znak "^[\\+|-]?". Pre hex hodnoty, ak očakávate, že hodnoty začať s "0x", som navrhne, napíš pred termín s tými, doslovný hodnoty.

2021-12-09 23:34:58

No podčiarkuje, a to nemusí zodpovedať skutočnej celé čísla. A samozrejme hranice (^$) by nemali pracovať so nájsť, ale to je začiatok...
Maarten Bodewes

@MaartenBodewes Ďakujem. Ja udeliť podčiarkuje, ale to, čo chceš povedať, že to nemusí zodpovedať skutočnej celé čísla? Tiež som nevedel, hranice, nefungujú find. Takže, ďakujem za to, že ako dobre.
hfontanez

Ospravedlňujeme sa, moje zlé, myslel som, že sa to nezhoduje s literály, ako sa uvádza v JLS, kde budete musieť mať 0x alebo 0X pre hexadecimálne atď.
Maarten Bodewes

@MaartenBodewes okrem som napísal " ak očakávate, že hodnoty začať s "0x", som navrhne, napíš pred termín s tými, doslovný hodnoty"
hfontanez

V iných jazykoch

Táto stránka je v iných jazykoch

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