2013-02-26 3 views
0

Я установил формат для String, который будет всегда: SPXXX-SPYYY.zipИзвлечение номера из фиксированного формата строки

мне нужно извлечь XXX и YYY из String, но если например XXX 003, тогда я хочу иметь и не 003. (То же самое для YYY).

Я написал эти два кода:

1.

String st = "SP003-SP012.zip"; 
String[] splitted = st.split("\\."); 
splitted = splitted[0].split("-"); 
splitted = splitted[0].split("P"); 
Integer in = new Integer(splitted[1]); 
System.out.println(in); //Will print 3 
//The same for the other part of the String 

2.

Pattern pattern = Pattern.compile("^[a-zA-Z]+([0-9]+).*"); 
Matcher matcher = pattern.matcher(st); 
int num = 0; 
while (matcher.find()) { 
    num = Integer.parseInt(matcher.group(1)); 
    System.out.println(num); 
} 
  • Почему второй код возвращает только первый номер? (XXX) и пропускает второй?
  • Какой код лучше для этой цели?
+1

Ваш первый код (разделение) и второй уже используют регулярные выражения !! – Juvanis

+0

@Juvanis Я неправильно понял себя :) исправлено. – Maroun

ответ

4

Если это всегда тот же формат, то почему бы просто не использовать substring?

String str = "SP003-SP456.zip"; 
int xxx = Integer.parseInt(str.substring(2, 5)); 
int yyy = Integer.parseInt(str.substring(8, 11)); 

Или, если те XXX и YYY не обязательно числа, то просто добавьте try-catch:

String str = "SP003-SP456.zip"; 
int xxx, yyy; 

try { 
    int xxx = Integer.parseInt(str.substring(2, 5)); 
} 
catch(NumberFormatException e) { 
    xxx = 0; 
} 

try { 
    int yyy = Integer.parseInt(str.substring(8, 11)); 
} 
catch(NumberFormatException e) { 
    yyy = 0; 
} 
1

Почему второй код возвращает только первый номер? (XXX) и пропустит второй?

Поскольку ваше регулярное выражение определяет только то, что оно ожидает увидеть одну цифру цифр и имеет только одну группу захвата для их захвата. Регулярное выражение ожидает увидеть буквы, за которыми следуют цифры, и находит только одно, что соответствует этому. (После того, как первый бит потребляется, там не осталось букв, так что ничто не соответствует вашему [a-zA-Z]+.) Вместо того, чтобы пытаться запустить сличитель несколько раз, я бы, вероятно, определить регулярное выражение, которое соответствовало оба бита:

Pattern pattern = Pattern.compile("^[a-zA-Z]+([0-9]+)-([0-9]+).*"); 

... и используйте полученные две группы захвата. (Также обратите внимание, вы можете использовать \d, чтобы соответствовать цифре:

Pattern pattern = Pattern.compile("^[a-zA-Z]+(\\d+)-(\\d+).*"); 

... но это примечание стороны.)

использует регулярное выражение для этой цели лучше, чем первый код, который я предложил ?

Это зависит от вас, это решение суда. Для этого конкретного случая, если формат действительно инвариантен, я бы пошел с Aleks G's approach.

1

Используйте следующее:

Pattern pattern = Pattern.compile("^[a-zA-Z]+0*(\\d+)-[a-zA-Z]+0*(\\d+).*"); 
Matcher matcher = pattern.matcher(st); 
if (matcher.matches()) { 
    int num1 = Integer.parseInt(matcher.group(1)); 
    int num2 = Integer.parseInt(matcher.group(2)); 
    System.out.println(num1+" - "+num2); 
} 
1

Почему второй код возвращает только первый номер? (XXX) и пропустил второй?

Если вы посмотрите на шаблон - "^[a-zA-Z]+([0-9]+).*", он имеет якорь caret - ^ в самом начале. Это означает, что ваш шаблон будет искать только в начале строки. И именно поэтому у вас есть только первый номер, соответствующий SPXXX, который находится в начале строки "SPXXX-SPYYY", а не для шаблона SPYYY, так как он не в начале и, следовательно, не будет соответствовать.

Вы можете удалить caret (^), и вы не хотите, чтобы .* в конце, так как вы используете метод Matcher#find().

Pattern pattern = Pattern.compile("[a-zA-Z]+([0-9]+)"); 

Но, учитывая, что ваша строка всегда будет находиться в том же формате, вы можете даже использовать простой шаблон:

Pattern pattern = Pattern.compile("\\d+"); 

и получить группы 1 из согласовани ,

Какой код лучше для этой цели?

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

1

Определить образец, как этот Pattern.compile("[a-zA-Z]+([0-9]+)");

Для примера строка matcher матчи SPXXX и SPYYY для двух итераций цикла.

И group(1) возвращает XXX и YYY для двух случаев соответственно.

Смежные вопросы