Tamsayı değişmeziyle eşleşecek normal ifade

0

Soru

tamsayıların bir listesini (bir özellik dizesinden) ayrıştırmayı düşünüyordum. Ancak, yalnızca pozitif ve negatif ondalık değerlerin ötesine geçmek ve kaynak kodunda bulunabileceği gibi bir Java tamsayı değişmezini (JLS 17) gösteren herhangi bir dizeyi ayrıştırmak istiyorum. Benzer şekilde, tamsayıların etrafındaki tüm önekler, ayırıcılar ve ekler konusunda da hoşgörülü olmak istiyorum. Başka bir deyişle, onları tekrarlanan çağrıları kullanarak bulmak istiyorumMatcher.find().

Tüm olası Java tamsayı değişmezleriyle eşleşen normal bir ifade var mı? Üst ve alt sınırları kontrol etmesine gerek yoktur.


JLS'YE açıkça bağlantı kurmuş olmama rağmen, bazı geçerli ve geçersiz numaralar göstereceğim:

  • -1: bu 1 eşleştirilir, ancak eksi tek bir operatördür (gerekirse ayarlarım)
  • 0x00_00_00_0F: onbeş değeri, iki nibble'ı ayırmak için bir alt çizgi ile onaltılık basamak olarak eşleştirilir
  • 0b0000_1111: ikili değer onbeş eşleştirilir
  • 017: on beşin sekizli değeri eşleştirilir
integer java literals regex
2021-11-23 21:48:28
3

En iyi cevabı

4

Böyle bir şey :

ondalık:
(?:0|[1-9](?:_*[0-9])*)[lL]?

onaltılık:
0x[a-fA-F0-9](?:_*[a-fA-F0-9])*[lL]?

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

ikilik:
0[bB][01](?:_*[01])*[lL]?

Hep birlikte: (freespacing modunda)

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

test et

2021-11-23 22:47:19

Evet, bu beni uzun bir yola sokar. Ama birden fazla altını çiziyor izin vermiyor? Belki de bu ? bir olmalı *?
Maarten Bodewes

@MaartenBodewes: Doktoru anladığım kadarıyla, alt çizgilerin sürekli olması gerekmiyor, ama belki de yanılıyorum? (başka bir deyişle 1____1 izin var mı ?). İsteğe bağlı alt çizginin içinde bulunduğu grubun sonunda yineleneceğini unutmayın.
Casimir et Hippolyte

Şu regex'i yeniden yazabilen var mı? Bunu güncelleyebiliyormuşum gibi görünüyordu (test sürümü hala var mıydı ? yerine *)....
Maarten Bodewes

Tekrar teşekkürler, regex'inizdeki ruha dayalı normal ifade sözdizimini kullanarak tamsayıyı da ayrıştıran bir cevap yayınladım.
Maarten Bodewes
0

Casimir'den gelen cevaptan sonra biraz daha ileri gitmeye karar verdim ve aşağıda yer alan tamsayıları da ayrıştırmak için bazı kodlar uyguladım. Bunlar resmi olarak jls'de açıklandığı gibi tamsayı değişmezinin bir parçası olmasa da eksi ve artı sembollerini içerir; bunlar tek işleçlerdir.

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

Ayrıca bir dizeden birden çok tamsayı bulmak için kodu kullanmaya çalıştım, ancak bu iyi gitmedi. Sorun, aşağıdaki gibi bazı geçersiz değişmezlerin olmasıdır 0__0 sıfır değeri olan iki değişmez olarak kabul edildi; tam olarak istediğin şey değil. Bu nedenle, lütfen yalnızca bir dizenin aslında bir tamsayı olup olmadığını tespit etmek için regex'i kullanın ve tamsayıları ayırın, örn. String.split(SEPARATOR_REGEX).

Eclipse ıde'm yeterince komik kabul etti 0__0 resmi olarak JLS ile uyumlu olmasa bile, gerçek olarak. Bir biggy, ama garip hiçbiri-daha az.

2021-11-23 22:27:00

Hızlı görünüm cevap, üzgünüm çok yorgun gitmek daha derin, ama dikkat çekmek için değil, çok fazla yakalar özellikle eğer sana ihtiyacım yok onlara. Yakalamayan grupları kullanma (?:....) (yakalamaların bir maliyeti vardır).
Casimir et Hippolyte

Mümkün olduğunda yakalamayan gruplar kullanıyorum. Belki tüm tamsayıyı doğrulamak için birkaçını kaldırabilirim; İlk eşleşme için onlara ihtiyacım yok. Ya da belki ilk eşleşmenin tamamını kaldırabilir ve olası tüm formatları doğrulayan döngüyü bırakabilirim. Ama sonunda tamsayıları eşleştirmeye çalışıyoruz, sayfa ve metin sayfalarını değil...
Maarten Bodewes
-1

İyi.... en basit ifadeyle, temel 2, 8 ve 10 sayıları, değerlerinin tümü sayısal karakterler olduğundan aynı deseni kullanabilir. ANCAK, muhtemelen her tür için bir ifade istersiniz. Sorun şu ki niyetini açıkça belli etmedin. İfadenin belirli bir değerin hangi temel olduğunu doğrulamasını istediğiniz varsayımına gidiyorum.

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

Sekizli ve ondalık değerler için, isteğe bağlı bir işaret karakteri olup olmadığını kontrol etmek için ifadenizi önceden göndermeniz gerekir "^[\\+|-]?". Onaltılık değerler için, değerlerin "0x" ile başlamasını beklerseniz, ifadeyi bu değişmez değerlerle önceden göndermenizi öneririm.

2021-12-09 23:34:58

Alt çizgi yok ve gerçek tamsayılarla eşleşmiyor. Ve tabii ki sınırlar (^$) find ile çalışmaz, ancak bu bir başlangıçtır...
Maarten Bodewes

@MaartenBodewes Teşekkür ederim. Sana alt çizgileri veriyorum ama gerçek tam sayılarla uyuşmuyor da ne demek? Ayrıca, sınırların işe yaramadığını bilmiyordum find. Bu yüzden, onun için de teşekkür ederim.
hfontanez

Üzgünüm, benim hatam, jls'de belirtildiği gibi değişmezlerle eşleşmediğini kastettim, burada sahip olmanız gereken yer 0x veya 0X onaltılıklar vb.İçin.
Maarten Bodewes

@ MaartenBodewes " değerlerin "0x" ile başlamasını bekliyorsanız, ifadeyi bu değişmez değerlerle önceden göndermenizi öneririm"yazmam dışında
hfontanez

Diğer dillerde

Bu sayfa diğer dillerde

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