Checking page numbers / ranges for printing
I am writing a regex to match a specific pattern that looks like this.
We are all familiar with the pattern we give when printing selected pages through a word document. i.e.
- We can use comma and hyphen
- no other special characters are allowed
- must start and end with a number
- Comma and hyphen are not allowed together, etc.
Valid values:
1, 3, 6-9 1-5, 5 6, 9
Invalid values:
,5 5-,9 9-5, 2,6-
I am using a pattern (([0-9]+)|(\\d.*[-,]\\d.*)+)
, but it doesn't work for all combinations of permutations.
Any help would be greatly appreciated!
source to share
The following regex will check that it is a comma-separated list of either a positive natural number or a range of a number (consisting of 2 positive natural numbers separated by a character -
):
^\d+(-\d+)?(?:,\d+(?:-\d+)?)*+$
In a string literal:
"^\\d+(-\\d+)?(?:,\\d+(?:-\\d+)?)*+$"
If you are wondering about *+
, this is the possessive version of the normal 0 or more quantifier *
. Basically, this reduces the return. This syntax is available in Java and PCRE, but omit +
in for languages without support *+
.
source to share
A bit late, but here is a class from my library that I rewrote recently. Let's take an argument like "1,2,3-6,4-5" and print out a list of distinct integers [1,2,3,4,5,6]. There will be some open source library that will do this for you by now ... didn't look much, but since I already had the ok class.
package se.imagick.scrap;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class RangeParser {
public static void main(String[] args) {
String ranges = "1,2,3-6,4-5";
List<Integer> rangeList = getDistinctNumbers(ranges);
System.out.println(rangeList);
}
public static List<Integer> getDistinctNumbers(String ranges) {
return Arrays.stream(ranges.split(","))
.map(s -> s.replace(" ", ""))
.map(Range::new)
.flatMap(range -> range.render().stream())
.distinct()
.sorted()
.collect(Collectors.toList());
}
private static class Range {
private int start;
private int stop;
public Range(String rangeStr) {
String[] rangeArray = rangeStr.split("-");
int length = rangeArray.length;
if (length < 1 || length > 2) {
throw new IllegalArgumentException("Wrong number of arguments in a Range: " + length);
}
start = Integer.parseInt(rangeArray[0]);
stop = (length == 1) ? start : Integer.parseInt(rangeArray[1]);
if (stop < start) {
throw new IllegalArgumentException("Stop before start!");
}
}
public List<Integer> render() {
List<Integer> pageList = new ArrayList<>(stop - start + 1);
for (Integer i = start; i < stop + 1; i++) {
pageList.add(i);
}
return pageList;
}
}
}
source to share