Personally, I don't like using regex to solve this kind of problem. The alternative to using regex as mentioned in the comments is to build a scanner and parser from a Backus-Naur description for a phone number. The description appears below:
<phone number> ::= <area code>-<central office>-<station code>
<area code> ::= <digit><digit><digit>
<central office> ::= <digit><digit><digit>
<station code> ::= <digit><digit><digit><digit>
<digit> ::= 0|1|2|3|4|5|6|7|8|9
The scanner and parser is as follows:
import java.util.Scanner;
public class PhoneNumberParser {
PhoneNumber number;
int look; // Current char read
int index; // Index into input buffer
String input; // Raw phone number input
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
PhoneNumberParser parser = new PhoneNumberParser();
try {
PhoneNumber number = parser.parse(scanner.nextLine());
System.out.println(number);
}catch(IllegalArgumentException ex) {
System.err.println(ex);
}
}
public PhoneNumber parse(String s) throws IllegalArgumentException{
number = new PhoneNumber();
input = s;
index = 0;
//if( s.length() != 10 )
// throw new IllegalArgumentException("Bad phone number. Expected a ten digit number.");
scan();
number.areaCode = areaCode();
scan();
if( look != '-')
throw new IllegalArgumentException("Bad phone number. Expected a '-' after the area code.");
scan();
number.centralOffice = centralOffice();
scan();
if( look != '-')
throw new IllegalArgumentException("Bad phone number. Expected a '-' after the central office part.");
scan();
number.stationCode = stationCode();
return number;
}
private void scan() {
try {
look = input.charAt(index++);
}catch(Exception ex) {
look = -1;
}
}
private int areaCode() {
StringBuffer sb = new StringBuffer();
sb.append(digit());
scan();
sb.append(digit());
scan();
sb.append(digit());
return Integer.parseInt(sb.toString());
}
private int centralOffice() {
StringBuffer sb = new StringBuffer();
sb.append(digit());
scan();
sb.append(digit());
scan();
sb.append(digit());
return Integer.parseInt(sb.toString());
}
private int stationCode() {
StringBuffer sb = new StringBuffer();
sb.append(digit());
scan();
sb.append(digit());
scan();
sb.append(digit());
scan();
sb.append(digit());
return Integer.parseInt(sb.toString());
}
private int digit() {
if( ! Character.isDigit((char) look) )
throw new IllegalArgumentException("Bad phone number. Expected a digit, but found a '" + (char)look + "' character.");
int digit = (char)look - '0';
return digit;
}
class PhoneNumber {
int areaCode;
int centralOffice;
int stationCode;
public String toString() {
return "Area code: " + areaCode + " Central office: " + centralOffice + " Station code: " + stationCode;
}
}
}
Output when supplied with the string 999-888-1234 is:
Area code: 999 Central office: 888 Station code: 1234
As you can see, the scanner parser gives better error reporting for bad numbers than regexp and also separates out the number into its constituent parts for further processing. For example, it may be important to just display the area code portion of the number.