diff --git a/sources/net.sf.j2s.core/dist/swingjs/SwingJS-site.zip b/sources/net.sf.j2s.core/dist/swingjs/SwingJS-site.zip index 3aa49df06..f45c92653 100644 Binary files a/sources/net.sf.j2s.core/dist/swingjs/SwingJS-site.zip and b/sources/net.sf.j2s.core/dist/swingjs/SwingJS-site.zip differ diff --git a/sources/net.sf.j2s.core/dist/swingjs/differences.txt b/sources/net.sf.j2s.core/dist/swingjs/differences.txt index c9ec02783..4e3c9213e 100644 --- a/sources/net.sf.j2s.core/dist/swingjs/differences.txt +++ b/sources/net.sf.j2s.core/dist/swingjs/differences.txt @@ -1468,7 +1468,8 @@ Formatter/Regex limitations Some browsers cannot process Regex "look-behind" process such as (?<=\W) java.util.regex.Matcher and Pattern use JavaScript's RegExp object rather than the native Java object. These are not identical. Only flags /igm are supported. -Matcher.start(groupID) is not supported. +Matcher.start(groupID)/.end(groupID) is supported. +(x*)? failure returns null, not empty string. java.util.Formatter will function correctly for all standard %... patterns. diff --git a/sources/net.sf.j2s.core/dist/swingjs/timestamp b/sources/net.sf.j2s.core/dist/swingjs/timestamp index a04c4689f..2898c400e 100644 --- a/sources/net.sf.j2s.core/dist/swingjs/timestamp +++ b/sources/net.sf.j2s.core/dist/swingjs/timestamp @@ -1 +1 @@ -20230304111725 +20230311212845 diff --git a/sources/net.sf.j2s.core/dist/swingjs/ver/3.3.1/SwingJS-site.zip b/sources/net.sf.j2s.core/dist/swingjs/ver/3.3.1/SwingJS-site.zip index 3aa49df06..f45c92653 100644 Binary files a/sources/net.sf.j2s.core/dist/swingjs/ver/3.3.1/SwingJS-site.zip and b/sources/net.sf.j2s.core/dist/swingjs/ver/3.3.1/SwingJS-site.zip differ diff --git a/sources/net.sf.j2s.core/dist/swingjs/ver/3.3.1/differences.txt b/sources/net.sf.j2s.core/dist/swingjs/ver/3.3.1/differences.txt index c9ec02783..4e3c9213e 100644 --- a/sources/net.sf.j2s.core/dist/swingjs/ver/3.3.1/differences.txt +++ b/sources/net.sf.j2s.core/dist/swingjs/ver/3.3.1/differences.txt @@ -1468,7 +1468,8 @@ Formatter/Regex limitations Some browsers cannot process Regex "look-behind" process such as (?<=\W) java.util.regex.Matcher and Pattern use JavaScript's RegExp object rather than the native Java object. These are not identical. Only flags /igm are supported. -Matcher.start(groupID) is not supported. +Matcher.start(groupID)/.end(groupID) is supported. +(x*)? failure returns null, not empty string. java.util.Formatter will function correctly for all standard %... patterns. diff --git a/sources/net.sf.j2s.core/dist/swingjs/ver/3.3.1/timestamp b/sources/net.sf.j2s.core/dist/swingjs/ver/3.3.1/timestamp index a04c4689f..2898c400e 100644 --- a/sources/net.sf.j2s.core/dist/swingjs/ver/3.3.1/timestamp +++ b/sources/net.sf.j2s.core/dist/swingjs/ver/3.3.1/timestamp @@ -1 +1 @@ -20230304111725 +20230311212845 diff --git a/sources/net.sf.j2s.java.core/dist/SwingJS-site.zip b/sources/net.sf.j2s.java.core/dist/SwingJS-site.zip index 3aa49df06..f45c92653 100644 Binary files a/sources/net.sf.j2s.java.core/dist/SwingJS-site.zip and b/sources/net.sf.j2s.java.core/dist/SwingJS-site.zip differ diff --git a/sources/net.sf.j2s.java.core/dist/differences.txt b/sources/net.sf.j2s.java.core/dist/differences.txt index c9ec02783..4e3c9213e 100644 --- a/sources/net.sf.j2s.java.core/dist/differences.txt +++ b/sources/net.sf.j2s.java.core/dist/differences.txt @@ -1468,7 +1468,8 @@ Formatter/Regex limitations Some browsers cannot process Regex "look-behind" process such as (?<=\W) java.util.regex.Matcher and Pattern use JavaScript's RegExp object rather than the native Java object. These are not identical. Only flags /igm are supported. -Matcher.start(groupID) is not supported. +Matcher.start(groupID)/.end(groupID) is supported. +(x*)? failure returns null, not empty string. java.util.Formatter will function correctly for all standard %... patterns. diff --git a/sources/net.sf.j2s.java.core/doc/Differences.txt b/sources/net.sf.j2s.java.core/doc/Differences.txt index c9ec02783..4e3c9213e 100644 --- a/sources/net.sf.j2s.java.core/doc/Differences.txt +++ b/sources/net.sf.j2s.java.core/doc/Differences.txt @@ -1468,7 +1468,8 @@ Formatter/Regex limitations Some browsers cannot process Regex "look-behind" process such as (?<=\W) java.util.regex.Matcher and Pattern use JavaScript's RegExp object rather than the native Java object. These are not identical. Only flags /igm are supported. -Matcher.start(groupID) is not supported. +Matcher.start(groupID)/.end(groupID) is supported. +(x*)? failure returns null, not empty string. java.util.Formatter will function correctly for all standard %... patterns. diff --git a/sources/net.sf.j2s.java.core/src/java/util/regex/Matcher.java b/sources/net.sf.j2s.java.core/src/java/util/regex/Matcher.java index b6e4e35f3..dda80cded 100644 --- a/sources/net.sf.j2s.java.core/src/java/util/regex/Matcher.java +++ b/sources/net.sf.j2s.java.core/src/java/util/regex/Matcher.java @@ -25,6 +25,7 @@ package java.util.regex; +import java.util.ArrayList; import java.util.Objects; /** @@ -143,11 +144,11 @@ public String toString() { */ Pattern pat; -// /** -// * The storage used by groups. They may contain invalid values if -// * a group was skipped during the matching. -// */ -// int[] groups; + /** + * The storage used by groups. They may contain invalid values if + * a group was skipped during the matching. + */ + int[] groups; /** * The range within the sequence that is to be matched. Anchors will match at @@ -241,11 +242,23 @@ public String toString() { private Object[] replacementParts; + /** + * the raw result from JavaScript regex execution + */ + private String[] 秘results; + private String[] results; private String strString; private int groupCount; + + /** + * raw group count + */ + private int 秘groupCount; + + private boolean 秘haveGroups; /** * No default constructor. @@ -273,8 +286,8 @@ public MatchResult toMatchResult() { Matcher result = new Matcher(pat, cs.toString()); result.first = first; result.last = last; - result.groupCount = groupCount; - result.results = results.clone(); + result.秘groupCount = 秘groupCount; + result.秘results = 秘results.clone(); return result; } @@ -297,9 +310,6 @@ public Matcher usePattern(Pattern newPattern) { if (newPattern == null) throw new IllegalArgumentException("Pattern cannot be null"); pat = newPattern; - -// int parentGroupCount = Math.max(newPattern.capturingGroupCount, 10); -// groups = new int[parentGroupCount * 2]; clearGroups(); return this; } @@ -342,7 +352,7 @@ static RegExp clone(RegExp rg) { public Matcher reset() { first = -1; last = 0; - groupCount = 0; + 秘groupCount = 0; oldLast = -1; clearGroups(); appendPos = 0; @@ -431,17 +441,15 @@ boolean search(int from, int anchor) { RegExp rg = pat.regexp; rg.lastIndex = from; acceptMode = (anchor == UNSPECIFIED ? NOANCHOR : anchor); - results = execRE(rg, s); - boolean result = checkRE(results, s); + 秘results = execRE(rg, s); + boolean result = checkRE(秘results, s); this.oldLast = last; return result; } private void clearGroups() { -// for (int i = 0; i < groups.length; i++) -// groups[i] = -1; -// for (int i = 0; i < locals.length; i++) -// locals[i] = -1; + 秘haveGroups = false; + groups = null; } /** @@ -607,6 +615,8 @@ private String processRepl(String replacement) { null); } this.replacement = replacement; + if (replacement != null && replacement.indexOf("$") >= 0) + 秘updateGroups(); // Process substitution string to replace group references with groups int index = 0; int replacementPos = 0; @@ -940,6 +950,7 @@ public String group(int group) { // this array is coming from JavaScript RegExp; some values may be "undefined" // so we force them to be null. return results[group] == null ? null : results[group]; +// JavaScript does not need this // if ((groups[group*2] == -1) || (groups[group*2+1] == -1)) // return null; // return getSubSequence(groups[group * 2], groups[group * 2 + 1]).toString(); @@ -974,7 +985,7 @@ public String group(int group) { public String group(String name) { int group = getMatchedGroupIndex(name); return group < 0 || group >= results.length ? null : group(group); -// +// JavaScript does not need this // if ((groups[group*2] == -1) || (groups[group*2+1] == -1)) // return null; // return getSubSequence(groups[group * 2], groups[group * 2 + 1]).toString(); @@ -996,9 +1007,35 @@ public String group(String name) { */ @Override public int groupCount() { + 秘updateGroups(); return groupCount; } + private void 秘updateGroups() { + if (秘haveGroups || 秘groupCount <= 0 || 秘results == null) + return; + 秘haveGroups = true; + pat.秘setNameGroups(); + ArrayList names = pat.秘groupNames; + int pt = start(); + groupCount = -1; + groups = new int[names.size() * 2]; + results = new String[秘results.length]; + for (int i = 0, gpt = 0, n = names.size(); i < n; i++) { + String name = names.get(i); + String r = 秘results[i]; + int len = (r == null ? 0 : r.length()); + if (name == null || !name.startsWith("秘")) { + groups[gpt++] = pt; + groups[gpt++] = pt + len; + pat.namedGroups().put(name, groupCount); + results[++groupCount] = r; + } else { + pt += len; + } + } + } + /** * Attempts to match the entire region against the pattern. * @@ -1033,8 +1070,8 @@ boolean match(int from, int anchor) { return result; } - private int indexRE(String[] results) { - return /** @j2sNative results.index || */ + private int indexRE(String[] r) { + return /** @j2sNative r.index || */ 0; } @@ -1050,7 +1087,7 @@ private boolean checkRE(String[] r, String s) { first = -1; return false; } - groupCount = r.length - 1; + 秘groupCount = r.length - 1; int f0 = this.first; first = indexRE(r); last = first + r[0].length(); @@ -1060,7 +1097,7 @@ private boolean checkRE(String[] r, String s) { // a longer string return false; } - if (groupCount < 0) + if (秘groupCount < 0) return false; switch (acceptMode) { case STARTANCHOR: @@ -1330,11 +1367,10 @@ int getMatchedGroupIndex(String name) { Objects.requireNonNull(name, "Group name"); if (first < 0) throw new IllegalStateException("No match found"); - if (pat.namedGroups == null) - pat.秘setNameGroups(); + 秘updateGroups(); if (pat.namedGroups == null || !pat.namedGroups().containsKey(name)) throw new IllegalArgumentException("No group with name <" + name + ">"); - return pat.namedGroups().get(name); + return pat.namedGroups().get(name).intValue() + 1; } /** * Returns the start index of the previous match. @@ -1380,9 +1416,9 @@ public int start(int group) { throw new IllegalStateException("No match available"); if (group < 0 || group > groupCount()) throw new IndexOutOfBoundsException("No group " + group); - return NOT_AVAILABLE; -// -// return groups[group * 2]; + if (group == 0) + return start(); + return groups[group * 2]; } /** @@ -1404,9 +1440,8 @@ public int start(int group) { * @since 1.8 */ public int start(String name) { - getMatchedGroupIndex(name); - return NOT_AVAILABLE; -// return groups[getMatchedGroupIndex(name) * 2]; + int g = getMatchedGroupIndex(name); + return groups[g * 2]; } /** @@ -1452,9 +1487,10 @@ public int end(int group) { throw new IllegalStateException("No match available"); if (group < 0 || group > groupCount()) throw new IndexOutOfBoundsException("No group " + group); - return NOT_AVAILABLE; + if (group == 0) + return end(); + return groups[group * 2 + 1]; -// return groups[group * 2 + 1]; } /** @@ -1476,9 +1512,8 @@ public int end(int group) { * @since 1.8 */ public int end(String name) { - getMatchedGroupIndex(name); - return NOT_AVAILABLE; -// return groups[getMatchedGroupIndex(name) * 2 + 1]; + int g = getMatchedGroupIndex(name); + return groups[g * 2 + 1]; } } diff --git a/sources/net.sf.j2s.java.core/src/java/util/regex/Pattern.java b/sources/net.sf.j2s.java.core/src/java/util/regex/Pattern.java index bf0111da9..524c6115b 100644 --- a/sources/net.sf.j2s.java.core/src/java/util/regex/Pattern.java +++ b/sources/net.sf.j2s.java.core/src/java/util/regex/Pattern.java @@ -37,19 +37,9 @@ import java.util.stream.Stream; import java.util.stream.StreamSupport; +import javajs.util.SB; import swingjs.JSUtil; -//import java.text.Normalizer; -//import java.util.Locale; -//import java.util.Iterator; -//import java.util.Arrays; -//import java.util.NoSuchElementException; -//import java.util.Spliterator; -//import java.util.Spliterators; -//import java.util.function.Predicate; -//import java.util.stream.Stream; -//import java.util.stream.StreamSupport; - /** * A compiled representation of a regular expression. * @@ -1421,6 +1411,11 @@ public final class Pattern { */ private String pattern; + /** + * full-group pattern for JavaScript start(int) and end(int) + */ + String 秘pattern; + /** * The original pattern flags. * @@ -1435,15 +1430,20 @@ public final class Pattern { private transient volatile boolean compiled = false; /** - * Map the "name" of the "named capturing group" to its group id node. + * Map the "name" of the "named capturing group" to its index in results */ transient volatile Map namedGroups; /** - * The number of capturing groups in this Pattern. Used by matchers to allocate - * storage needed to perform a match. + * group names, in order */ - transient int capturingGroupCount; + ArrayList 秘groupNames = new ArrayList(); + +// /** +// * The number of capturing groups in this Pattern. Used by matchers to allocate +// * storage needed to perform a match. +// */ +// transient int capturingGroupCount; /** * Index into the pattern string that keeps track of how much has been parsed. @@ -1876,9 +1876,10 @@ private void compile() { checkFlags(); pattern = removeQEQuoting(pattern); + 秘pattern = 秘getJSpattern(pattern); // GLOBAL is always important, since it allows the // RegExp to seek multiple times using an iterator - regexp = newRegExp(pattern, getFlags(flags | GLOBAL)); + regexp = newRegExp(秘pattern, getFlags(flags | GLOBAL)); compiled = true; } @@ -1942,11 +1943,96 @@ private static String getFlags(int flags) { return flagStr; } - private static RegExp newRegExp(String pattern, String flags) { - return /** @j2sNative new RegExp(pattern, flags) || */ + private static RegExp newRegExp(String 秘pattern, String flags) { + return /** @j2sNative new RegExp(秘pattern, flags) || */ null; } + /** + * if any groups exist, or even could exist, + * + * @param pattern + * @return + */ + private static String 秘getJSpattern(String pattern) { + if (pattern.indexOf("(") < 0) + return pattern; + SB p = new SB(); + int ntext = 0; + boolean ignore = false; + boolean isChar = false; + for (int i1 = -1, plen = 0, i = 0, n = pattern.length(); i < n; i++) { + char c = pattern.charAt(i); + switch (c) { + default: + isChar = true; + break; + case '*': + case '+': + case '?': + isChar = true; + if (i1 < 0) { + p.appendC(c); + continue; + } + break; + case '[': + if (!ignore && i1 == -1) { + plen = p.length(); + i1 = i; + } + ignore = true; + isChar = true; + break; + case ']': + ignore = false; + isChar = true; + break; + case ')': + case '(': + if (ignore) + break; + isChar = false; + boolean isQ = (c == '(' && pattern.charAt(i + 1) == '?'); + boolean isColon = (isQ && pattern.charAt(i + 2) == ':'); + int i0 = i; + if (isColon) { + i = pattern.indexOf(')', i); + p.append(pattern.substring(i0, i + 1)); + continue; + } + if (i1 >= 0) { + p.insert(plen, "(?<秘" + ++ntext + ">"); + p.append(")"); + i1 = -1; + } + if (isQ) { + if (pattern.charAt(i + 2) == '<') { + i = pattern.indexOf(">", i); + p.append(pattern.substring(i0, i + 1)); + continue; + } + } + break; + } + if (isChar) { + if (!ignore && i1 == -1) { + plen = p.length(); + i1 = i; + } + if (c == '\\') { + p.appendC(c); + c = pattern.charAt(++i); + } + } + p.appendC(c); + } +// if (!haveStart) { +// p.insert(0, "(?<秘" + ++ntext + ">$.*)"); +// } + return p.toString(); + } + /** * Indicates whether a particular flag is set or not. */ @@ -2176,9 +2262,11 @@ public boolean hasNext() { * JavaScript hack for no named groups. */ void 秘setNameGroups() { + if (namedGroups != null) + return; namedGroups(); - String s = this.pattern; - int pt = s.lastIndexOf("(?<") + 1; + String s = this.秘pattern; + int pt = s.lastIndexOf("(") + 1; if (pt == 0) return; boolean ignore = false; @@ -2199,21 +2287,30 @@ public boolean hasNext() { if (ignore) continue; n++; - if (s.charAt(i + 1) == '?') { + String name = null; + if (s.charAt(i + 1) == '?') { switch (s.charAt(i + 2)) { - case '<': - String name = s.substring(i + 3, s.indexOf(">", i)); - namedGroups.put(name, n); - i += s.indexOf(")", i); // ok if this is \\) + case '<': + int i1 = s.indexOf(">", i); + name = s.substring(i + 3, i1); + if (name.startsWith("秘")) { + n--; + } else { + namedGroups.put(name, n); + } + i = i1; break; case ':': n--; - break; - } + continue; + } } + if (秘groupNames.size() == 0) + 秘groupNames.add(null); + 秘groupNames.add(name); break; } } - + } } diff --git a/sources/net.sf.j2s.java.core/src/test/Test_Regex.java b/sources/net.sf.j2s.java.core/src/test/Test_Regex.java index c6ed2d44b..084a8d172 100644 --- a/sources/net.sf.j2s.java.core/src/test/Test_Regex.java +++ b/sources/net.sf.j2s.java.core/src/test/Test_Regex.java @@ -3,6 +3,7 @@ import java.util.Arrays; import java.util.HashMap; import java.util.Map; +import java.util.regex.MatchResult; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -10,22 +11,128 @@ public class Test_Regex extends Test_ { public static void main(String[] args) { - - - String st; Pattern p; Matcher m; - st = "NMR DATA/product/3a-C'.mnova"; - p = Pattern.compile("^\\QNMR DATA/\\E[^|/]+\\Q/\\E(?(?(?[^|/]+)\\Q-\\E[^|/]+)\\Q.mnova\\E)$"); - m = p.matcher(st); + String s; + + String formatSpecifier; + + // groups + + + formatSpecifier = "%(y?x*)?"; + p = Pattern.compile(formatSpecifier); + m = p.matcher("%d"); + m.find(0); + System.out.println(m.groupCount()); + for (int i = 0; i <= m.groupCount();i++) { + s = m.group(i); + // note that in JavaScript (x*)? returns null, not (as in Java) "" + System.out.println(i + " " + s); + } + + + + formatSpecifier = "%(\\d+\\$)?([-#+ 0,(\\<]*)?(\\d+)?(\\.\\d+)?([tT])?([a-zA-Z%])"; + p = Pattern.compile(formatSpecifier); + m = p.matcher("%d"); + m.find(0); + System.out.println(m.groupCount()); + for (int i = 0; i <= m.groupCount();i++) { + s = m.group(i); + // note that in JavaScript ([-#+ 0,(\\<]*)? returns null, not (as in Java) "" + System.out.println(i + " " + s); + } + + String s0; + s0 = "x/2 is a very excellent 1/x or x"; + s = (" " + s0 + " ").replaceAll("(\\W)x(\\W)", "$1y$2").trim(); + System.out.println(s); + assert ("y/2 is a very excellent 1/y or y".equals(s)); + + s0 = "x/2 is a very excellent 1/x or x"; + s = (" " + s0 + " ").replaceAll("(?\\W)x(?\\W)", "${test1}y${test2}").trim(); + System.out.println(s); + assert ("y/2 is a very excellent 1/y or y".equals(s)); + + + formatSpecifier = "%(x*)?"; + p = Pattern.compile(formatSpecifier); + m = p.matcher("%d"); + m.find(); + System.out.println(m.groupCount()); + for (int i = 0; i <= m.groupCount();i++) { + s = m.group(i); + System.out.println(i + " " + s); + } + + + + + + + p = Pattern.compile("(\\W)y(\\W)"); + m = p.matcher("(m*(@^2+~^2)/r+m*g*(1-y/r))*(1-y/r)"); + s = m.replaceAll("$1`$2").trim(); + assert (m.groupCount() == 2); + System.out.println(s); + assert ("(m*(@^2+~^2)/r+m*g*(1-`/r))*(1-`/r)".equals(s)); + + s = Pattern.compile("(\\W)y(\\W)").matcher(" y+ y*2 ").replaceAll("$1`$2").trim(); + System.out.println(s); + assert ("`+ `*2".equals(s)); + + Map vars = new HashMap<>(); + vars.put("a2", Double.valueOf(2)); + vars.put("a3", Double.valueOf(3)); + assert (eval("y+a2*x+a3", vars).equals("y+(2.0)*x+(3.0)")); + assert (eval("y + a2*x + a3", vars).equals("y+(2.0)*x+(3.0)")); + assert (eval("y + -a2*x + a3", vars).equals("y+-(2.0)*x+(3.0)")); + + + // testing without \Q \E + s = Arrays.toString(splitUnquoted("this[a-z] is \"a[a-z]test\"", "[a-z]")); + System.out.println(s); + assert (s.equals("[, , , , [, -, ] , , \"a[a-z]test\"]")); + + // testing \Q \E -- caveat that quoted \Q \E is not supported + s = Arrays.toString(splitUnquoted("this[a-z] is \"a[a-z]test\"", Pattern.quote("[a-z]"))); + System.out.println(s); + assert (s.equals("[this, is \"a[a-z]test\"]")); + + // testing \Q \E -- nonspecial quote + s = Arrays.toString(splitUnquoted("this; is \"a;test\"", Pattern.quote(";"))); + System.out.println(s); + assert (s.equals("[this, is \"a;test\"]")); + + + + Object[] o = new Object[] { new Float(3.5), Integer.valueOf(100)}; + s = String.format("val=%5.3f Completed %d%%.", o); + System.out.println(s); + assert(s.equals("val=3.500 Completed 100%.")); + + + p = Pattern.compile("(this/(?:[^/]+/)*).+\\Q.pdf\\E$");//$"); + m = p.matcher("this/is/a/test/testing.1.pdf"); System.out.println(m.find()); + // note that go [1,n] here, not [0,n) for (int i = 1, n = m.groupCount(); i <= n; i++) { System.out.println(i + "/" + n + ">"+m.group(i)+"<"); } - + st = "FID for Publication/S6.zip|S6/HRMS.zip|HRMS/67563_hazh180_maxis_pos.pdf"; + p = Pattern.compile("^\\QFID for Publication/\\E(?[^|/]+)\\Q.zip" + + "|\\E\\k\\Q/HRMS.zip|\\E(?:[^/]+/)*(?[^|/]+\\Q.pdf\\E)$"); + m = p.matcher(st); + System.out.println(m.find()); + for (int i = 1, n = m.groupCount(); i <= n; i++) { + System.out.println(i + "/" + n + ">"+m.group(i)+"<"); + } + + st = "...pre-20a-b/DEPT135/3/pdata/1/procs"; st = "...pre-20a-b/DEPT135|3/pdata/1/procs"; p = Pattern.compile("^(?.+(?:/|\\|)(?[^/]+))/pdata/[^/]+/procs$"); @@ -36,15 +143,36 @@ public static void main(String[] args) { } - st = "FID for Publication/S6.zip|S6/HRMS.zip|HRMS/67563_hazh180_maxis_pos.pdf"; - p = Pattern.compile("^\\QFID for Publication/\\E(?[^|/]+)\\Q.zip" - + "|\\E\\k\\Q/HRMS.zip|\\E(?:[^/]+/)*(?[^|/]+\\Q.pdf\\E)$"); + + st = "NMR DATA/product/3a-C'.mnova"; + p = Pattern.compile("^\\QNMR DATA/\\E[^|/]+\\Q/\\E(?(?(?[^|/]+)\\Q-\\E[^|/]+)\\Q.mnova\\E)$"); m = p.matcher(st); System.out.println(m.find()); for (int i = 1, n = m.groupCount(); i <= n; i++) { System.out.println(i + "/" + n + ">"+m.group(i)+"<"); } + + + + String lipsum = "Lorem ipsum dolor sit amet ipsum"; + p = Pattern.compile("(?(?ip(?s)u)(?m))"); + m = p.matcher(lipsum); + m.find(); + MatchResult mr = m.toMatchResult(); + m.find(); + +// System.out.println("g0" + m.group("g0") + " " + m.start("g0") + " " + m.end("g0")); +// System.out.println("g1" + m.group("g1") + " " + m.start("g1") + " " + m.end("g1")); +// System.out.println("g2" + m.group("g2") + " " + m.start("g2") + " " + m.end("g2")); + System.out.println(m.group(0) + " " + m.start() + " " + m.end()); + for (int i = 0;i <= m.groupCount(); i++) { + System.out.println(i + " " + m.group(i) + " " + m.start(i) + " " + m.end(i)); + } + for (int i = 0;i <= mr.groupCount(); i++) { + System.out.println(i + " " + mr.group(i) + " " + mr.start(i) + " " + mr.end(i)); + } + st = "{abc::now {jkl::{def::and} {ghi::then}}}"; p = Pattern.compile("\\{([^:]+)::(.+)\\}"); m = p.matcher(st); @@ -62,7 +190,7 @@ public static void main(String[] args) { for (int i = 1, n = m.groupCount(); i <= n; i++) { System.out.println(i + "/" + n + ">"+m.group(i)+"<"); } - assert(m.group("IFSnmr0param0expt").equals("test")); + assert(m.group("IFS0nmr0param0expt").equals("test")); p = Pattern.compile("(?i)ID(?.+) and this is id \\k"); m = p.matcher("ID1 and this is id 1"); @@ -102,41 +230,11 @@ public static void main(String[] args) { System.out.println(i + "/" + n + ">"+m.group(i)+"<"); } - p = Pattern.compile("this/([^/]+/)*(.+[.]pdf)$");//$"); - m = p.matcher("this/is/a/test/testing.pdf"); - m.find(); - // note that go [1,n] here, not [0,n) - for (int i = 1, n = m.groupCount(); i <= n; i++) { - System.out.println(i + "/" + n + ">"+m.group(i)+"<"); - } - - p = Pattern.compile("(this/(?:[^/]+/)*).+\\Q.pdf\\E$");//$"); - m = p.matcher("this/is/a/test/testing.1.pdf"); - m.find(); - // note that go [1,n] here, not [0,n) - for (int i = 1, n = m.groupCount(); i <= n; i++) { - System.out.println(i + "/" + n + ">"+m.group(i)+"<"); - } - String s; - Object[] o = new Object[] { new Float(3.5), Integer.valueOf(100)}; - s = String.format("val=%5.3f Completed %d%%.", o); - System.out.println(s); - assert(s.equals("val=3.500 Completed 100%.")); - - String formatSpecifier - = "%(\\d+\\$)?([-#+ 0,(\\<]*)?(\\d+)?(\\.\\d+)?([tT])?([a-zA-Z%])"; - Pattern fsPattern = Pattern.compile(formatSpecifier); - Matcher fm = fsPattern.matcher("%d"); - fm.find(0); - System.out.println(fm.groupCount()); - for (int i = 0; i < fm.groupCount();i++) { - s = fm.group(i); - // note that in JavaScript ([-#+ 0,(\\<]*)? returns null, not (as in Java) "" - System.out.println(s); - } - + + + System.out.println("testRE pattern def"); s = Pattern.compile("''").matcher("ab'cd''ef'''gh''''").replaceAll("X"); System.out.println(s); @@ -153,45 +251,8 @@ public static void main(String[] args) { System.out.println(s); assert (s.equals("XX")); - // groups - String s0 = "x/2 is a very excellent 1/x or x"; - s = (" " + s0 + " ").replaceAll("(\\W)x(\\W)", "$1y$2").trim(); - System.out.println(s); - assert ("y/2 is a very excellent 1/y or y".equals(s)); - - p = Pattern.compile("(\\W)y(\\W)"); - m = p.matcher("(m*(@^2+~^2)/r+m*g*(1-y/r))*(1-y/r)"); - s = m.replaceAll("$1`$2").trim(); - assert (m.groupCount() == 2); - System.out.println(s); - assert ("(m*(@^2+~^2)/r+m*g*(1-`/r))*(1-`/r)".equals(s)); - - s = Pattern.compile("(\\W)y(\\W)").matcher(" y+ y*2 ").replaceAll("$1`$2").trim(); - System.out.println(s); - assert ("`+ `*2".equals(s)); - - Map vars = new HashMap<>(); - vars.put("a2", Double.valueOf(2)); - vars.put("a3", Double.valueOf(3)); - assert (eval("y+a2*x+a3", vars).equals("y+(2.0)*x+(3.0)")); - assert (eval("y + a2*x + a3", vars).equals("y+(2.0)*x+(3.0)")); - assert (eval("y + -a2*x + a3", vars).equals("y+-(2.0)*x+(3.0)")); - - - // testing without \Q \E - s = Arrays.toString(splitUnquoted("this[a-z] is \"a[a-z]test\"", "[a-z]")); - System.out.println(s); - assert (s.equals("[, , , , [, -, ] , , \"a[a-z]test\"]")); - - // testing \Q \E -- caveat that quoted \Q \E is not supported - s = Arrays.toString(splitUnquoted("this[a-z] is \"a[a-z]test\"", Pattern.quote("[a-z]"))); - System.out.println(s); - assert (s.equals("[this, is \"a[a-z]test\"]")); + - // testing \Q \E -- nonspecial quote - s = Arrays.toString(splitUnquoted("this; is \"a;test\"", Pattern.quote(";"))); - System.out.println(s); - assert (s.equals("[this, is \"a;test\"]")); System.out.println("Test_Regex OK"); }