i have a string which loads on the page based on the success and failure search results. If the search case is success then my output table will have a string like
Search Results - 31 Items Found (Debug Code: 4b50016efc3a1ad93502)
or if my search results fail, then the output table will display a string either:
Search Results - No data found (Debug Code: 4b50016efc3a1ad93502)
Search Results - 0 Items Found (Debug Code: 4b50016efc3a1ad93502)
Search Results - An Exception Occurred (Debug Code: 4b50016efc3a1ad93502)
depending on the input conditions.
I want to extract the Debug Code value and pass on to other scenario to validate further. I know I can use substring() to extract the Debug Code, but its position in the string is not constant; it varies based on the input conditions, however Debug code will be at last.
How can I extract the Debug Code value (eg 4b50016efc3a1ad93502) for all scenarios?
You can use regex to capture and return the target code:
String debugCode = output.replaceAll(".*Debug Code: (\\w+).*|.*", "$1");
What's happening here?
The regex .*Debug Code: (\\w+).* matches the entire string, and captures (with brackets) the target text using \\w+, which means "one or more 'letter' characters" ('letters' included digits). The replacement string $1 means "group 1" - the first captured group. Because the entire input is matched, this operation effectively replaces the whole input with the captured group, so returns just the target text.
So what happens if the input doesn't have a debug code?
The extra |.* at the end of the regex means "or 'anything'", so the regex will match the entire input even if there it doesn't have a debug code, but captured group 1 will still exist, but it will be empty, so the operation returns the blank string.
Examples:
String output1 = "Results - 0 Items Found (Debug Code: 4b50016efc3a1ad93502)";
String output2 = "something else";
String code1 = output1.replaceAll(".*Debug Code: (\\w+).*|.*", "$1"); // "4b50016efc3a1ad93502"
String code2 = output2.replaceAll(".*Debug Code: (\\w+).*|.*", "$1"); // ""
You don't have to use "|.*", but you don't have it, the entire string will be returned if the input doesn't have the 'debug code' format.
A java String is invariant. No matter how you get a String, its contents will not change.
For example
String s = "the way we were";
String t = s.substring(4, 6); // t = "way"
s = "abcdefghijk";
s is a new String, but t is unchanged
Related
I have a response string like as follows
21.03.2019_15:06.26 [SELOGER]:: [Seloger value]-[PROGRESS]: marminto=true, france24=true,
Using Java I have to validate the above response is printed in following format:
<date+time> [SELOGER]:: [Seloger value]-[<PROGRESS|STOP|START>]: <value1>=<true|false>, <value2>=<true|false>........
first is <date+time> then [SELOGER]:: [Seloger value]- then [PROGRESS or STOP or START]: then values marminto=true, france24=true,.....
How can i perform this with regex? or any java API's available to detect a string is printed in particular format.
Try this pattern:
\d{2}\.\d{2}\.\d{4}\_\d{2}:\d{2}\.\d{2} \[SELOGER\]:: \[Seloger value\]-\[(?:PROGRESS|STOP|START)\]: *(?:[a-zA-Z0-9]+=(?:true|false), ?)*
Explanation:
\d{2}\.\d{2}\.\d{4}\_\d{2}:\d{2}\.\d{2} matches date in specified format
(?:PROGRESS|STOP|START) - conditional, match any from PROGRESS, STOP or START
(?:[a-z0-9]+=(?:true|false), ?)* - match zero or more value=true/value=false pairs optionally followed by space and followed by comma
Demo
Input -
String ipXmlString = "<root>"
+ "<accntNoGrp><accntNo>1234567</accntNo></accntNoGrp>"
+ "<accntNoGrp><accntNo>6663823</accntNo></accntNoGrp>"
+ "</root>";
Tried follwing things using to mask values within using
String op = ipXmlString .replaceAll("<accntNo>(.+?)</accntNo>", "######");
But above code masks all the values
<root><accntNoGrp>######</accntNoGrp><accntNoGrp>######</accntNoGrp></root>
Expected Output:
<root><accntNoGrp><accntNo>#####67</accntNo></accntNoGrp><accntNoGrp><accntNo>#####23</accntNo></accntNoGrp></root>
How to achieve this using java regex ?Could someone help
Your replacement is wrong, you need to include the <accntNo> tag in the actual replacement. Also, it appears that you want to show the last two characters/numbers of the account number. In this case, we can capture this information during the match and use it in the replacement.
Code:
String op = ipXmlString.replaceAll("<accntNo>(?:.+?)(.{2})</accntNo>", "<accntNo>######$1</accntNo>");
Explanation:
<accntNo> match an opening tag
(?:.+?) match, but do not capture, anything up until the first
(.{2}) two characters before closing tag (and capture this)
</accntNo> match a closing tag
Note here that by using ?: inside a parenthesis in the pattern, we tell the regex engine to not capture it. There is no point in capturing anything before the last two characters of the account number because we don't want to us it.
The $1 quantity in the replacement refers to the first capture group. In this case, it is the last two characters of the account number. Hence, we build the replacement string you want this way.
Demo here:
Rextester
Try this code:
public static void main(String[] args) {
String ipXmlString = "<root>"
+ "<accntNoGrp><accntNo>1234567</accntNo></accntNoGrp>"
+ "<accntNoGrp><accntNo>6663823</accntNo></accntNoGrp>"
+ "</root>";
String replaceAll = ipXmlString.replaceAll("\\d+", "######");
System.out.println(replaceAll);
}
Prints:
<root><accntNoGrp><accntNo>######</accntNo></accntNoGrp><accntNoGrp><accntNo>######</accntNo></accntNoGrp></root>
This is the sample code
String m_testPattern = "AB.*?";
String m_testMatcherString = "ABCDCDCDCD";
final Pattern pattern = Pattern.compile(m_testPattern);
final Matcher matcher = pattern.matcher(m_testMatcherString);
if (matcher.matches()) {
// This means the regex matches
System.out.println("Successful comparison");
} else {
// match failed
System.out.println("Comparison failed !!!");
}
Ideally the match operation should result in a failure and give me output as "Comparison failed !!!"
But this code snippet gives me "Successful comparison" as output
I checked online regex tools with the same input and the result was different
I did the trial in this site http://regexr.com/v1/
Here when I put AB.*? in the regex and ABCDCDCDCD as the string to be compared, then the search stops at AB.
This means the comparison performed is a Lazy Comparison and not a greedy one
Can anyone please explain why the same use case fails in case of Java Pattern.match function ?
My test case is something like
1. regex AB\wCD should match with ABZCD plus fail at AB2CD
2. AB\w{2}CD would match ABZZCD
3. AB\d{1,3}CD should match AB555CD or AB6CD or AB77CD plus fail at ABCD or AB9999CD etc
4. AB.* should match AB(followed by anything)
5. AB.*? should fail if input like ABCDCDCD is given for comparison
All the 4 steps is passed successfully while using matcher.matches() function <br/>
Only the fifth one gives a wrong answer. (5th scenario also gives a success message eventhough it should fail)
Thanks in advance
matches()
return true if the whole string matches the given pattern.
find()
tries to find a substring that matches the pattern.
I want to replace some parts of a String with Regex. It's the 192001Z part of the string I want to replace.
Code:
String met = "192001Z 17006KT 150V210 CAVOK 11/07 Q1004 NOSIG";
String regexZ = "[0-9].{5}Z";
met = met.replaceAll(regexZ, "${.now?string(\"ddHHmm\")}Z");
I get an error when I want to replace a part of the String with ${.now?string(\"ddHHmm\")}Z.
But when I e.g. replace ${.now?string(\"ddHHmm\")}Z with ThisNeedsToBeReplaced everything works just fine. So my guess is that something is wrong with the string I want to use to replace parts of my original string (met).
The error I receive is Illegal group reference.
Does anyone have an idea what's wrong with ${.now?string(\"ddHHmm\")}Z?
You need to use:
met = met.replaceAll("\\b\\d{6}Z\\b", "\\${.now?string(\"ddHHmm\")}Z");
Correct regex to match 192001Z is \b\d{6}Z\b
You need to escape $ in replacement as well otherwise it is considered a back reference e.g. $1, $2 etx.
I am referring to the test harness listed here http://docs.oracle.com/javase/tutorial/essential/regex/test_harness.html
The only change I made to the class is that the pattern is created as below:
Pattern pattern =
Pattern.compile(console.readLine("%nEnter your regex(Pattern.CANON_EQ set): "),Pattern.CANON_EQ);
As the tutorial at http://docs.oracle.com/javase/tutorial/essential/regex/pattern.html suggests I put in the pattern or regex as a\u030A and string to match as \u00E5 but it ends on a No Match Found. I saw both the strings are a small case 'a' with a ring on top.
Have I not understood the use case correctly?
The behavior you're seeing has nothing to do with the Pattern.CANON_EQ flag.
Input read from the console is not the same as a Java string literal. When the user (presumably you, testing out this flag) types \u00E5 into the console, the resultant string read by console.readLine is equivalent to "\\u00E5", not "å". See for yourself: http://ideone.com/lF7D1
As for Pattern.CANON_EQ, it behaves exactly as described:
Pattern withCE = Pattern.compile("^a\u030A$",Pattern.CANON_EQ);
Pattern withoutCE = Pattern.compile("^a\u030A$");
String input = "\u00E5";
System.out.println("Matches with canon eq: "
+ withCE.matcher(input).matches()); // true
System.out.println("Matches without canon eq: "
+ withoutCE.matcher(input).matches()); // false
http://ideone.com/nEV1V