
shz.RegexHelp Maven / Gradle / Ivy
package shz;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.Date;
import java.util.Map;
import java.util.function.Function;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* (?d) Unix中的行
* (?i) 不区分大小写
* (?m) 多行
* (?s) 单行(dotall)
* (?u) Unicode
* (?x) 忽略空格和注释
* ()捕获分组,(?:)非捕获分组
* (?>)关闭回溯
* 前瞻,后顾(非捕获)
* (?=)正前瞻,(?!)反前瞻,(?<=)正后顾,(?
* 空白符
* \f 换页,\h 水平空白符,\H 非水平空白符,\n 换行符,\r 回车符,\t 水平制表符,\v 垂直制表符,\V 非垂直制表符
*
* 字符简写式
* \a 报警符,[\b] 退格字符,\b 单词边界,\B 非单词边界,\cx 控制字符,\d 数字字符,\D 非数字字符,\dxxx 字符的十进制值,\oxxx 字符的八进制值
* \s 空白符,\S 非空白符,\w 单词字符,\W 非单词字符,\0 空字符,\x xx 字符的十六进制值,\\u xxxx 字符的Unicode值
*
* posix字符组
* [[:ascii:]] ASCII字符(128个)
* [[:graph:]] 图形字符
* [[:print:]] 可打印字符
* [[:punct:]] 标点符号
* [[:space:]] 空格符号
*/
public final class RegexHelp {
private RegexHelp() {
throw new IllegalStateException();
}
public static final String CHAR = "^[\u0000-\uffff]$";
public static final String BOOLEAN = "^0|1|(?i:true|false)$";
public static final String UNSIGNED_BYTE = "^\\d|[1-9]\\d|1[01]\\d|12[0-7]$";
public static final String BYTE = "^0|-128|[\\-]?(?:[1-9]|[1-9]\\d|1[01]\\d|12[0-7])$";
public static final String UNSIGNED_DIGITAL = "^0|0\\.\\d+|[1-9]\\d*(?:\\.\\d+)?$";
public static final String DIGITAL = "^0|[\\-]?(?:0\\.\\d+|[1-9]\\d*(?:\\.\\d+)?)$";
public static final String PHONE = "^(?:13[0-9]|14[5,7,9]|15(?:[0-3]|[5-9])|166|17[0,1,3,5,6,7,8]|18[0-9]|19[8|9])\\d{8}$";
public static final String CH_PHONE = "^\\d{3}-\\d{8}|\\d{4}-\\d{7}$";
public static final String EMAIL = "^\\w+@\\w+(?:\\.\\w+)+$";
public static final String IP = "^(?:(?:2(?:5[0-5]|[0-4]\\d))|1?\\d{1,2})(?:\\.(?:(?:2(?:5[0-5]|[0-4]\\d))|1?\\d{1,2})){3}$";
public static final String DOMAIN = "(?:^[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\\.)+[a-zA-Z]{2,6}$";
public static final String URL = "^(?:(?:https?|ftp|file)://)?(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\\.)+[a-zA-Z]{2,6}(?::[1-5]\\d{1,4})?(?:/[\\w.@-_]+)*$";
public static final String HTML = "<[_a-zA-Z][^>]*/>|<([_a-zA-Z][\\w]*+)[^>]*>.*?\\1>";
public static final String CH_POSTAL_CODE = "^[1-9]\\d{5}(?!\\d)$";
public static final String QQ = "^[1-9][0-9]{4,10}$";
public static final String NAME_CH = "^[\u4e00-\u9fa5]{2,4}$";
public static final String NAME_CH_MINORITY = "^[\u4e00-\u9fa5]+(?:[·•.][\u4e00-\u9fa5]+)*$";
public static final String NAME_EN = "^[a-zA-Z\\s]+(?:[·•.][a-zA-Z]+)*$";
public static final String LOGIN_NAME = "^[a-zA-Z0-9·•.]{3,20}$";
public static final String PWD = "^[a-zA-Z0-9!\"#\\$%&'\\(\\)\\*\\+,-\\./:;<=>\\?@\\[\\\\\\]\\^_`\\{\\|\\}~]{4,16}$";
public static final String NO = "^[0-9a-zA-Z]{1,64}$";
public static final String MIDDLE_CH = "^[\u4e00-\u9fa5]{1,64}$";
public static final String CHAR_255 = "^[\u0000-\uffff]{0,255}$";
/**
* @param flags 正则表达式中出现了^或者$, 默认只会匹配第一行. 设置了Pattern.MULTILINE模式,会匹配所有行
* 默认情况下, 正则表达式中点(.)不会匹配换行符, 设置了Pattern.DOTALL模式, 才会匹配所有字符包括换行符
*/
public static String find(String s, int flags, String regex, int group) {
if (s == null || regex == null) return s;
Matcher matcher = Pattern.compile(regex, flags).matcher(s);
if (matcher.find()) return matcher.group(group);
return null;
}
public static String find(String s, String regex) {
return find(s, 0, regex, 0);
}
public static String find(String s, boolean all, int flags, String... regexes) {
if (s == null || regexes.length == 0) return s;
String result = find(s, flags, regexes[0], 0);
if (regexes.length == 1) return result;
if (result == null) {
if (regexes[0] != null) return null;
result = s;
}
int i = 1;
for (; i < regexes.length; ++i) {
if (regexes[i] == null) continue;
String find = find(result, flags, regexes[i], 0);
if (find != null) {
result = find;
continue;
}
result = all ? null : result;
break;
}
return result;
}
public static String find(String s, boolean all, String... regexes) {
return find(s, all, 0, regexes);
}
public static String find(String s, String... regexes) {
return find(s, true, 0, regexes);
}
public static String getHost(String url) {
return find(url, 0, "(//)?([\\w.]+)/", 2);
}
public static boolean isMatch(String s, String regex) {
return s != null && regex != null && Pattern.compile(regex).matcher(s).find();
}
public static boolean nonMatch(String s, String regex) {
return !isMatch(s, regex);
}
public static boolean isAnyMatch(String s, String regex1, String regex2) {
return isMatch(s, regex1) || isMatch(s, regex2);
}
public static boolean nonAnyMatch(String s, String regex1, String regex2) {
return !isAnyMatch(s, regex1, regex2);
}
public static boolean isAnyMatch(String s, String... regexes) {
return Arrays.stream(regexes).parallel().anyMatch(e -> isMatch(s, e));
}
public static boolean nonAnyMatch(String s, String... regexes) {
return !isAnyMatch(s, regexes);
}
public static boolean isAllMatch(String s, String regex1, String regex2) {
return isMatch(s, regex1) && isMatch(s, regex2);
}
public static boolean nonAllMatch(String s, String regex1, String regex2) {
return !isAllMatch(s, regex1, regex2);
}
public static boolean isAllMatch(String s, String... regexes) {
return Arrays.stream(regexes).parallel().allMatch(e -> isMatch(s, e));
}
public static boolean nonAllMatch(String s, String... regexes) {
return !isAllMatch(s, regexes);
}
public static String replace(String s, int flags, String regex, Function func) {
Matcher matcher = Pattern.compile(regex, flags).matcher(s);
StringBuilder sb = new StringBuilder();
int start = 0;
while (matcher.find()) {
sb.append(s, start, matcher.start());
sb.append(func.apply(matcher));
start = matcher.end();
}
sb.append(s, start, s.length());
return sb.toString();
}
public static String replace(String s, String regex, Function func) {
return replace(s, 0, regex, func);
}
public static boolean isLeapYear(int year) {
return year % 400 == 0 || (year % 4 == 0 && year % 100 != 0);
}
public static boolean isLeapYear(Object year) {
if (Validator.isBlank(year)) return false;
if (year instanceof Number) return isLeapYear(((Number) year).intValue());
else if (year instanceof CharSequence) return isLeapYear(Integer.parseInt(((String) year)));
else if (year instanceof LocalDateTime) return isLeapYear((LocalDateTime) year);
else if (year instanceof Instant) return isLeapYear(LocalDateTime.ofInstant((Instant) year, TimeHelp.ZONE_ID));
else if (year instanceof ZonedDateTime) return isLeapYear(((ZonedDateTime) year).toLocalDateTime());
else if (year instanceof Date)
return isLeapYear(LocalDateTime.ofInstant(Instant.ofEpochMilli(((Date) year).getTime()), TimeHelp.ZONE_ID));
return false;
}
private static final DateTimeFormatter Y_PATTERN = DateTimeFormatter.ofPattern("y");
private static boolean isLeapYear(LocalDateTime ldt) {
return isLeapYear(Integer.parseInt(ldt.format(Y_PATTERN)));
}
public static boolean isBirthday(String s) {
try {
LocalDateTime ldt = (LocalDateTime) ToObject.parse(s, LocalDateTime.class);
if (ldt == null) return false;
return isBirthday(ldt);
} catch (Exception e) {
return false;
}
}
private static final DateTimeFormatter M_PATTERN = DateTimeFormatter.ofPattern("M");
private static final DateTimeFormatter D_PATTERN = DateTimeFormatter.ofPattern("d");
private static boolean isBirthday(LocalDateTime ldt) {
if (ldt.isAfter(LocalDateTime.now())) return false;
if (!"2".equals(ldt.format(M_PATTERN))) return true;
if (Integer.parseInt(ldt.format(D_PATTERN)) < 29) return true;
return isLeapYear(ldt);
}
public static boolean isBirthday(Object obj) {
if (obj instanceof CharSequence) return isBirthday((String) obj);
else if (obj instanceof LocalDateTime) return isBirthday((LocalDateTime) obj);
else if (obj instanceof Instant) return isBirthday(LocalDateTime.ofInstant((Instant) obj, TimeHelp.ZONE_ID));
else if (obj instanceof ZonedDateTime) return isBirthday(((ZonedDateTime) obj).toLocalDateTime());
else if (obj instanceof Date)
return isBirthday(LocalDateTime.ofInstant(Instant.ofEpochMilli(((Date) obj).getTime()), TimeHelp.ZONE_ID));
return false;
}
private static final Map ID_R_C = ToMap.get(35)
.put("11", "北京").put("12", "天津").put("13", "河北").put("14", "山西")
.put("15", "内蒙古").put("21", "辽宁").put("22", "吉林").put("23", "黑龙江")
.put("31", "上海").put("32", "江苏").put("33", "浙江").put("34", "安徽")
.put("35", "福建").put("36", "江西").put("37", "山东").put("41", "河南")
.put("42", "湖北").put("43", "湖南").put("44", "广东").put("45", "广西")
.put("46", "海南").put("50", "重庆").put("51", "四川").put("52", "贵州")
.put("53", "云南").put("54", "西藏").put("61", "陕西").put("62", "甘肃")
.put("63", "青海").put("64", "宁夏").put("65", "新疆").put("71", "台湾")
.put("81", "香港").put("82", "澳门").put("91", "国外").build();
private static final int[] ID_W = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2};
private static final int[] ID_M = {1, 0, 10, 9, 8, 7, 6, 5, 4, 3, 2};
public static boolean isIdentity(String s) {
if (s == null) return false;
if (s.length() == 15) return isBirthday("19" + s.substring(6, 12));
if (s.length() != 18) return false;
if (!ID_R_C.containsKey(s.substring(0, 2))) return false;
int[] c_i = new int[17];
for (int i = 0; i < c_i.length; ++i) c_i[i] = s.charAt(i) - '0';
int sum = 0;
for (int i = 0; i < 17; ++i) sum += c_i[i] * ID_W[i];
char c = s.charAt(17);
return ID_M[sum % 11] == ((c == 'x' || c == 'X') ? 10 : c - '0');
}
/**
* 获取身份证号所在地区
*/
public static String getIdentityRegion(String identity) {
if (!isIdentity(identity)) return null;
return ID_R_C.get(identity.substring(0, 2));
}
/**
* 判断是否卡号
*/
public static boolean luhnCheck(String s) {
if (s == null || !s.matches("^\\d{8,19}$")) return false;
return luhnCompute(s.substring(0, s.length() - 1)) == s.charAt(s.length() - 1) - '0';
}
/**
* 计算卡号校验位
*/
public static int luhnCompute(String s) {
Validator.requireNon(s == null || !s.matches("^\\d{7,18}$"));
int mod = luhnSum(s) % 10;
return mod == 0 ? 0 : 10 - mod;
}
private static int luhnSum(String s) {
int sum = 0;
for (int i = s.length() - 1, j = 0; i > -1; --i, ++j) {
int n = s.charAt(i) - '0';
if ((j & 1) == 0) {
n <<= 1;
n = n / 10 + n % 10;
}
sum += n;
}
return sum;
}
}