Regex извлекает числа всех длин

1

Я пытаюсь извлечь номера длиной от 3 до 5 из длинной строки текста. Позволь мне объяснить

Скажем, есть строка, подобная этой 123456 и я хочу извлечь все число, которое находится между выводами длины 3 и 5, будет

123
234
345
456
1234
2345
3456
12345
23456

Я могу запустить несколько регулярных выражений, которые индивидуально находят длины, но может быть лучший способ сделать это, чем то, что я делаю.

import java.io.IOException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class RegexTestHarness {

    public static void main(String[] args) throws IOException {

        String data = "123456";

        Matcher m = Pattern.compile("\\d{3}").matcher(data);

        // m = Pattern.compile("\\d{4}").matcher(data);
        // m = Pattern.compile("\\d{5}").matcher(data);

        int position = 0;

        while (m.find(position++)) {
            System.out.println(m.group());
        }
    }
}

Преждевременная оптимизация Идея - я могу сопоставить все с 5, а затем запускать матчи меньшего размера по результатам. Таким образом, я сокращаю время чтения данных, над которыми в моем случае является внешний источник.

Теги:

3 ответа

2
Лучший ответ

Вы можете сделать это с помощью одного регулярного выражения. Просто найти в мире.
Группы захвата печати 1,2,3, если их длина больше 0

 #  "(?=(\\d{3}))(?=(\\d{4}))?(?=(\\d{5}))?"

 (?=
      ( \d{3} )         # (1)
 )
 (?=
      ( \d{4} )         # (2)
 )?
 (?=
      ( \d{5} )         # (3)
 )?

Тест на Perl

while ( '123456' =~ /(?=(\d{3}))(?=(\d{4}))?(?=(\d{5}))?/g )
{
     print "$1\n";
     if ( length ($2) ) {
         print "$2\n";
     }
     if ( length ($3) ) {
         print "$3\n";
     }
}

Выход >>

123
1234
12345
234
2345
23456
345
3456
456
  • 1
    Впервые я когда-либо проголосовал за ответ в Perl на вопрос в Java.
  • 0
    Я всегда включаю простые тестовые сценарии Perl, но решения регулярных выражений всегда строго в помеченном языке языка OP. Спасибо.
Показать ещё 4 комментария
2

Это выглядит намного сложнее с регулярным выражением. Если вам не нужно использовать его, пройдите через каждую из исходных позиций и извлеките числа:

// If this string is just plain numbers, skip the dataArray and the
// for (String s: dataArray) and replace the s in the loops with data's

String data = "123456 some other datas 654321";
String[] dataArray = data.split("\\D+");

for (String s: dataArray){
    for (int length = 3; length <= 5; length++){
        for (int index = 0; index <= s.length() - length; index++) {
            int maxIndex = index + length;
            System.out.println(s.substring(index, maxIndex));
        }
    }
}

Вывод:

123
234
345
456
1234
2345
3456
12345
23456
654
543
432
321
6543
5432
4321
65432
54321
  • 0
    Где вы проверяете, что получаете только цифры?
  • 0
    @DavidWallace О, это было необходимо? Позвольте мне это исправить.
Показать ещё 7 комментариев
0

Попробуйте это решение только для 3-5 матчей. Я использую lookahead, чтобы найти совпадающее совпадение со строкой. Здесь я использовал три регулярных выражения.

String text = "123456";
Pattern pattern = Pattern.compile("(?=(\\d\\d\\d))(?=(\\d\\d\\d\\d?))(?=(\\d\\d\\d\\d?\\d?))");
Matcher m = pattern.matcher(text);

// taking out all the captures from the Matcher
List<String> list = new ArrayList<String>();
while (m.find()) {
    list.add(m.group(1));
    list.add(m.group(2));
    list.add(m.group(3));
}

// making the list unique using HashSet
list = new ArrayList<String>(new HashSet<String>(list));

// printing
for(String s : list){
    System.out.println(s);
}

// output is not sorted, if you want you can sort the List<>
  • 1
    Что делать, если ввод "1234 123" ? Вы могли бы действительно хотеть дубликаты.
  • 0
    @DavidWallace вы имеете в виду наличие пробела между ними?
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню