-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathCharacterClass.java
More file actions
145 lines (130 loc) · 5.56 KB
/
Copy pathCharacterClass.java
File metadata and controls
145 lines (130 loc) · 5.56 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
package Phase6_RuntimeMemoryRegexReflection.Regex;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Character Classes
* -----------------
* A CHARACTER CLASS is a regex construct that matches ONE CHARACTER drawn
* from a defined set. Three kinds:
* <p>
*
* 1. CUSTOM SETS [abc], [a-z], [a-zA-Z0-9_], [^abc]
* 2. PREDEFINED CLASSES \d \D \w \W \s \S .
* 3. POSIX / UNICODE CLASSES \p{Alpha}, \p{Digit}, \p{IsAlphabetic}
* <p>
*
* 1) Custom Character Sets
* ------------------------
* [abc] a, b, OR c
* [^abc] any char EXCEPT a, b, c
* [a-z] any lowercase letter (range)
* [a-zA-Z] union of ranges
* [a-z&&[^aeiou]] intersection - "lowercase consonant"
* <p>
*
* Inside [ ] most metacharacters lose their special meaning. The exceptions
* are: ] \ ^ (at the start) - (in the middle)
* <p>
*
* 2) Predefined Classes (shortcuts)
* ---------------------------------
* . any character EXCEPT a newline (unless DOTALL flag)
* \d a digit == [0-9]
* \D NOT a digit == [^0-9]
* \w "word" char == [a-zA-Z0-9_]
* \W NOT a word char
* \s whitespace == [ \t\n\x0B\f\r]
* \S NOT whitespace
* \h \H horizontal whitespace / not (Java 8+)
* \v \V vertical whitespace / not (Java 8+)
* <p>
*
* 3) POSIX & Unicode Classes
* --------------------------
* \p{Lower} [a-z]
* \p{Upper} [A-Z]
* \p{Alpha} letters
* \p{Digit} digits
* \p{Alnum} letters or digits
* \p{Space} whitespace
* \p{Punct} punctuation
* \p{ASCII} ASCII range 0..127
* <p>
*
* Unicode aware (require the UNICODE_CHARACTER_CLASS flag, or use \p{IsX}):
* \p{IsAlphabetic} letters from any script
* \p{IsLatin} Latin script
* \p{IsGreek} Greek script
* \p{InCyrillic} Unicode "block" (where the code point lives)
* \p{N} Number (general category)
* <p>
*
* Negation
* --------
* \P{Alpha} opposite of \p{Alpha}
* [^abc] negated custom set
* <p>
*
* Why care?
* ---------
* Character classes are the WORKHORSE of regex. Almost every real-world
* pattern is some quantified character class:
* \d{3}-\d{4} phone number
* [a-zA-Z0-9._%+-]+@... email local-part
* [^,]+ any field in a CSV line
*/
public class CharacterClass {
public static void main(String[] args) {
section("1) Custom sets - [abc], ranges, negation");
showMatches("[abc]", "cat in a basket"); // a, a, a
showMatches("[A-Za-z]", "JavaScript-26"); // letters only
showMatches("[^aeiou]", "abracadabra"); // non-vowels
showMatches("[a-z&&[^aeiou]]","abracadabra"); // lowercase consonants
section("2) Predefined classes - \\d, \\w, \\s, .");
showMatches("\\d", "a1b22c333"); // 1 2 2 3 3 3
showMatches("\\D", "a1b22c333"); // letters
showMatches("\\w", "a1 b@2"); // a 1 b 2
showMatches("\\W", "a1 b@2"); // @
showMatches("\\s", "a b\tc\nd"); // space tab newline
showMatches(".", "a b\tc\nd"); // every char except newline
section("3) POSIX classes - \\p{Alpha}, \\p{Digit}, etc.");
showMatches("\\p{Alpha}", "abc123XYZ-456");
showMatches("\\p{Digit}", "abc123XYZ-456");
showMatches("\\p{Alnum}", "Hello, World!");
showMatches("\\p{Punct}", "Hello, World!");
section("4) Unicode classes - works across scripts");
showMatches("\\p{IsAlphabetic}", "नमस्ते Hello Γειά"); // letters of any script
showMatches("\\p{IsLatin}", "नमस्ते Hello Γειά"); // Latin only
showMatches("\\p{IsGreek}", "नमस्ते Hello Γειά"); // Greek only
section("5) Negation - \\P{X} flips a Unicode class");
showMatches("\\P{Alpha}", "abc 123-xyz"); // non-letters
section("6) Common real-world uses");
// CSV field - non-comma chars
String[] fields = "alpha,beta,,gamma".split(",");
System.out.println("CSV fields = " + java.util.Arrays.toString(fields));
// Strip all non-digits
String digits = "Call (555) 867-5309".replaceAll("\\D", "");
System.out.println("digits only = " + digits);
// Keep only word chars
String slug = "Hello, World! 2026".replaceAll("\\W+", "-").toLowerCase();
System.out.println("slug = " + slug);
// OUTPUT (representative)
// ====== 1) Custom sets - [abc], ranges, negation ======
// [abc] in "cat in a basket" -> [a, a, a]
// [A-Za-z] in "JavaScript-26" -> [J, a, v, a, S, c, r, i, p, t]
// [^aeiou] in "abracadabra" -> [b, r, c, d, b, r]
// [a-z&&[^aeiou]] in "abracadabra" -> [b, r, c, d, b, r]
// ...
}
/** Find every match of `regex` in `text` and print them as a list. */
private static void showMatches(String regex, String text) {
Pattern p = Pattern.compile(regex);
Matcher m = p.matcher(text);
java.util.List<String> hits = new java.util.ArrayList<>();
while (m.find()) hits.add(m.group());
System.out.printf("%-20s in %-25s -> %s%n", regex, "\"" + text + "\"", hits);
}
private static void section(String title) {
System.out.println("\n====== " + title + " ======");
}
}