web-dev-qa-db-fra.com

Utilisation d'expressions régulières pour extraire une valeur en Java

J'ai plusieurs chaînes à l'état brut:

[some text] [some number] [some more text]

Je veux extraire le texte dans [un certain nombre] en utilisant les classes Java Regex.

Je sais à peu près quelle expression régulière je veux utiliser (bien que toutes les suggestions soient les bienvenues). Ce qui m'intéresse vraiment, ce sont les appels Java pour prendre la chaîne regex et l'utiliser sur les données source pour produire la valeur de [un certain nombre].

EDIT: Je devrais ajouter que je ne suis intéressé que par un seul [un certain nombre] (essentiellement, la première instance). Les chaînes source sont courtes et je ne vais pas chercher plusieurs occurrences de [un certain nombre].

145
Craig Walker

Exemple complet:

private static final Pattern p = Pattern.compile("^([a-zA-Z]+)([0-9]+)(.*)");
public static void main(String[] args) {
    // create matcher for pattern p and given string
    Matcher m = p.matcher("Testing123Testing");

    // if an occurrence if a pattern was found in a given string...
    if (m.find()) {
        // ...then you can use group() methods.
        System.out.println(m.group(0)); // whole matched expression
        System.out.println(m.group(1)); // first expression from round brackets (Testing)
        System.out.println(m.group(2)); // second one (123)
        System.out.println(m.group(3)); // third one (Testing)
    }
}

Puisque vous recherchez le premier numéro, vous pouvez utiliser cette expression rationnelle:

^\D+(\d+).*

et m.group(1) vous retournera le premier numéro. Notez que les nombres signés peuvent contenir un signe moins:

^\D+(-?\d+).*
283
Allain Lalonde
import Java.util.regex.Matcher;
import Java.util.regex.Pattern;

public class Regex1 {
    public static void main(String[]args) {
        Pattern p = Pattern.compile("\\d+");
        Matcher m = p.matcher("hello1234goodboy789very2345");
        while(m.find()) {
            System.out.println(m.group());
        }
    }
}

Sortie:

1234
789
2345
34
javaMan

Allain a fondamentalement le code Java, vous pouvez donc l'utiliser. Cependant, son expression ne correspond qu'à si vos nombres ne sont précédés que d'un flux de caractères Word. 

"(\\d+)"

devrait être capable de trouver la première chaîne de chiffres. Vous n'avez pas besoin de spécifier ce qui se trouve avant, si vous êtes sûr que ce sera la première chaîne de chiffres. De même, il est inutile de spécifier ce qui va suivre, à moins que vous ne le vouliez. Si vous voulez juste le numéro et que vous êtes sûr que ce sera la première chaîne d'un ou plusieurs chiffres, c'est tout ce dont vous avez besoin. 

Si vous vous attendez à ce qu’il soit compensé par des espaces, il sera encore plus distinct de spécifier 

"\\s+(\\d+)\\s+"

pourrait être mieux. 

Si vous avez besoin des trois parties, voici ce que vous ferez:

"(\\D+)(\\d+)(.*)"

EDITLes expressions données par Allain et Jack suggèrent que vous deviez spécifier un sous-ensemble de non-chiffres pour capturer digits. Si vous indiquez au moteur de regex que vous recherchez \d, il ignorera tout ce qui précède les chiffres. Si l'expression de J ou A correspond à votre motif, la correspondance entière est égale à la chaîne input. Et il n'y a aucune raison de le spécifier. Cela ralentit probablement une partie nette si elle n'est pas totalement ignorée. 

33
Axeman

En plus de Pattern , la classe Java String dispose également de plusieurs méthodes pouvant fonctionner avec des expressions régulières. Dans votre cas, le code sera le suivant:

"ab123abc".replaceFirst("\\D*(\\d*).*", "$1")

\\D est un caractère non numérique.

11
Vitalii Fedorenko

En Java 1.4 et supérieur:

String input = "...";
Matcher matcher = Pattern.compile("[^0-9]+([0-9]+)[^0-9]+").matcher(input);
if (matcher.find()) {
    String someNumberStr = matcher.group(1);
    // if you need this to be an int:
    int someNumberInt = Integer.parseInt(someNumberStr);
}
9
Jack Leow

Cette fonction collecte toutes les séquences correspondantes de la chaîne. Dans cet exemple, il prend toutes les adresses électroniques de la chaîne.

static final String EMAIL_PATTERN = "[_A-Za-z0-9-\\+]+(\\.[_A-Za-z0-9-]+)*@"
        + "[A-Za-z0-9-]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})";

public List<String> getAllEmails(String message) {      
    List<String> result = null;
    Matcher matcher = Pattern.compile(EMAIL_PATTERN).matcher(message);

    if (matcher.find()) {
        result = new ArrayList<String>();
        result.add(matcher.group());

        while (matcher.find()) {
            result.add(matcher.group());
        }
    }

    return result;
}

Pour message = "[email protected], <[email protected]>>>> [email protected]" il va créer une liste de 3 éléments.

6
LukaszTaraszka

Essayez de faire quelque chose comme ça:

Pattern p = Pattern.compile("^.+(\\d+).+");
Matcher m = p.matcher("Testing123Testing");

if (m.find()) {
    System.out.println(m.group(1));
}
3
Tint Naing Win

Solution simple

// Regexplanation:
// ^       beginning of line
// \\D+    1+ non-digit characters
// (\\d+)  1+ digit characters in a capture group
// .*      0+ any character
String regexStr = "^\\D+(\\d+).*";

// Compile the regex String into a Pattern
Pattern p = Pattern.compile(regexStr);

// Create a matcher with the input String
Matcher m = p.matcher(inputStr);

// If we find a match
if (m.find()) {
    // Get the String from the first capture group
    String someDigits = m.group(1);
    // ...do something with someDigits
}

Solution dans une classe utilitaire

public class MyUtil {
    private static Pattern pattern = Pattern.compile("^\\D+(\\d+).*");
    private static Matcher matcher = pattern.matcher("");

    // Assumptions: inputStr is a non-null String
    public static String extractFirstNumber(String inputStr){
        // Reset the matcher with a new input String
        matcher.reset(inputStr);

        // Check if there's a match
        if(matcher.find()){
            // Return the number (in the first capture group)
            return matcher.group(1);
        }else{
            // Return some default value, if there is no match
            return null;
        }
    }
}

...

// Use the util function and print out the result
String firstNum = MyUtil.extractFirstNumber("Testing4234Things");
System.out.println(firstNum);
2
NoBrainer

Regardez, vous pouvez le faire en utilisant StringTokenizer

String str = "as:"+123+"as:"+234+"as:"+345;
StringTokenizer st = new StringTokenizer(str,"as:");

while(st.hasMoreTokens())
{
  String k = st.nextToken();    // you will get first numeric data i.e 123
  int kk = Integer.parseInt(k);
  System.out.println("k string token in integer        " + kk);

  String k1 = st.nextToken();   //  you will get second numeric data i.e 234
  int kk1 = Integer.parseInt(k1);
  System.out.println("new string k1 token in integer   :" + kk1);

  String k2 = st.nextToken();   //  you will get third numeric data i.e 345
  int kk2 = Integer.parseInt(k2);
  System.out.println("k2 string token is in integer   : " + kk2);
}

Étant donné que nous prenons ces données numériques dans trois variables différentes, nous pouvons les utiliser n'importe où dans le code

1
shounak

Que diriez-vous de [^\\d]*([0-9]+[\\s]*[.,]{0,1}[\\s]*[0-9]*).* Je pense que cela s’occuperait des nombres avec une fraction. J'ai inclus les espaces et le , comme séparateur possible . J'essaie d'extraire les nombres d'une chaîne, y compris les flottants, en tenant compte du fait que l'utilisateur peut se tromper et inclure des espaces lors de la saisie .

0
arturo

Parfois, vous pouvez utiliser une simple méthode .split ("REGEXP") disponible dans Java.lang.String. Par exemple:

String input = "first,second,third";

//To retrieve 'first' 
input.split(",")[0] 
//second
input.split(",")[1]
//third
input.split(",")[2]
0
user1722707
Pattern p = Pattern.compile("(\\D+)(\\d+)(.*)");
Matcher m = p.matcher("this is your number:1234 thank you");
if (m.find()) {
    String someNumberStr = m.group(2);
    int someNumberInt = Integer.parseInt(someNumberStr);
}
0
User User