Regular expressions: 100 errors - java

I'm trying to learn about regular expressions but am not doing so well after reading through the java tutorial.
This program is supposed to take an imput in the format:
a) add dd dd together
b) subtract 05 from 13
c) add 02 to 03
And return the dd (+ or -) dd = answer
The (wrong) way I set this up is to have the prog try to find either of the 3 matches, and continue to do so until the user inputs "bye." If there isn't a match it should just prompt the user for an input again.
Here's my code! With exactly 100 errors. :/
If anyone can help me with the syntax, it'd really be appreciated!
import java.util.*;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
class Calculator {
public static void main(String[] args){
Scanner imp = new Scanner(System.in);
System.out.println("yes> ");
String s = imp.nextLine();
if (s.equals("bye")) {
System.exit(0);
}
while (true) {
Pattern p = Pattern.compile(s); //compile string, check for formats
Matcher x = p.matcher(\badd\b\s\d\d\s\d\d\s\btogether\b); //format add 12 12 together
Matcher y = p.matcher(\bsubtract\b\s\d\d\s\d\d\s\bfrom\b); //format subtract 05 from 13
Matcjer z = p.matcher(\badd\b\s\d\d\s\bto\b\s\d\d); //format add 02 to 03
boolean b = p.matches;
boolean l = x.matches;
boolean i = y.matches;
boolean g = z.matches;
if (l.equals(true))
return (\d\d " + " \d\d " = " \d\d+\d\d);
else if (i.equals(true))
return (\d\d " + " \d\d " = " \d\d-\d\d);
else if (g.equals(true))
return (\d\d " + " \d\d " = " \d\d+\d\d);
}
}
}

Have you tried looking at your code in an IDE such as Eclipse or IntelliJ IDEA? They'll highlight the errors for you. The main one I'm seeing is that you're not putting the regular expressions in strings. Java doesn't have native regexes, so you'll need to supply them as strings. Here's an example:
Matcher x = p.matcher("\\badd\\b\\s\\d\\d\\s\\d\\d\\s\\btogether\\b"); //format add 12 12 together
Notice how I've doubled up the backslashes. This is because it's the escape character in Java as well as in regexes. The compiler will interpret the above string as \badd\b\s\d\d\s\d\d\s\btogether\b, and then the regular expression parser will interpret the escape characters properly.

ugh where to begin...
first off Pattern.compile() is expecting the regex (the format strings) while matcher() expects the string to test against
#Samir has shown you what was wrong with the regexes in the code itself (I edited them a bit for more clarity)
l.matches needs ()
you cannot call methods on primitive boolean variables if(b) is sufficient to test if it is true or not
and to get specific submatches you need to use capturing groups
to concatenate strings together you can use +
to output something to the console System.out.println should be used not return
with the most obvious errors solved:
import java.util.*;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
class Calculator {
public static void main(String[] args){
Scanner imp = new Scanner(System.in);
System.out.println("yes> ");
while (true) {
String s = imp.nextLine();//put getting the input inside the loop or it's infinite
if (s.equals("bye")) {
System.exit(0);
}
Matcher x = Pattern.compile("add\\s(\\d+)\\s(\\d+)\\stogether").matcher(s); //format add 12 12 together
Matcher y = Pattern.compile("subtract\\s(\\d+)\\sfrom\\s(\\d+)").matcher(s); //format subtract 05 from 13
Matcjer z = Pattern.compile("add\\s(\\d+)\\sto\\s(\\d+)").matcher(s); //format add 02 to 03
boolean l = x.matches();
boolean i = y.matches();
boolean g = z.matches();
if (l){
System.out.println(l.group(1) + " + " + l.group(2) + " = " +
(Integer.parseInt(l.group(1))+Integer.parseInt(l.group(2))) );
}else if (i){
System.out.println(i.group(1) + " - " + i.group(2) + " = " +
(Integer.parseInt(i.group(1))+Integer.parseInt(i.group(2))) );
}else if (g){
System.out.println(g.group(1) + " + " + g.group(2) + " = " +
(Integer.parseInt(g.group(1))+Integer.parseInt(g.group(2))) );
}
}
}
}

Related

JDBCTemplate queryForMap compare and replace value in extracted lines

Can you help me to understand why my code doesn't work, please?
I am trying to get values from 2 columns from my database and store them in a hashmap where K_PARAM is my key and L_PARAM is my value. Then I would like to compare 2 characters from a line that I am extracting and see if these 2 characters are equals to my key or not. In case they are equals, I replace key with value.
Thanks in advance. This is the code :
if (action.equals("RP")) {
if (marqueCarte = null) {
jdbcTemplate.query(" select K_PARAM, L_PARAM from DLCOA.DLC_ADM_PARAMS where K_CHX_PARAM = '50'", new ResultSetExtractor<Map>(){
#Override
public Map extractData(ResultSet rs) throws SQLException,DataAccessException {
 HashMap<String,String> marqueCarte = new HashMap<String,String>();
while (rs.next()) {
marqueCarte.put(rs.getString("K_PARAM"),rs.getString("L_PARAM"));
if (line.contains("blocE")) {
if (line.substring(line.indexOf("blocE") + 15, line.indexOf("blocE") + 15 + (line.substring(line.indexOf("blocE")+15)).indexOf("#")).equals(rs.getString("K_PARAM"))){
line = line.replace(line.substring(line.indexOf("blocE") + 15, line.indexOf("blocE") + 15 + (line.substring(line.indexOf("blocE")+15)).indexOf("#")),rs.getString("L_PARAM") );
}
}
   }
return marqueCarte;
}
}
}
}
I got a more readable and modifiable solution for your second problem.
(I'm still not sure what's your first one)
Using regex and patterns you can achieve the replacement you want.
Let's assume that you are searching for the text "blocE" followed by 15 characters, followed at the same time by the text contained in rs.getString("K_PARAM") plus an "#"
We can model what you search as a pattern like this
"(blocE)(.{15})(" + key + "#)"
Parenthesis allow us to establish different groups in the regex.
Group 1 - blocE
Group 2 - 15 characters
Group 3 - key + #
Being group 0 the complete matching expression.
Knowing this you can do the replacement applying the following code
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class TestRegex {
public static void main(String[] args) {
String key = "KEY"; // rs.getString("K_PARAM")
String value = "VALUE"; // rs.getString("L_PARAM")
Pattern pattern = Pattern.compile("(blocE)(.{15})(" + key + "#)");
String input ="helloworldblocE111111111111111KEY#blocE111111111111111KEY";
Matcher m = pattern.matcher(input);
if (m.find()) {
String text2replace = m.group(0);
String replacement = m.group(1) + m.group(2) + value;
System.out.println(input.replaceFirst(text2replace, replacement));
}
}
}
If your pattern changes, you only have to change one line and you do not have to worry about such quantity of indexOf.

Regular expression in java always return true

Can you please help me with regex for the following string in android:
1.0.2 Build S6B5
How it should be:
{number}.{number}.{number}{space}Build{space}{S or D orT}{anything up 3 to 4 chars}
With help of some king people from here I`ve tried the flowing code:
if (name.matches("\\d+\\.\\d+\\.\\d+\\s+Build\\s[SDT].{3,4}"));
but it always return True even for:
1.0.1 4C0
1.0.1 B 4BD
1.0.4.52A
etc.
Try the following code:
public static void main (String[] args) {
String name1 = "1.0.1 4C0";
String name2 = "1.0.1 B 4BD";
String name3 = "1.0.4.52A";
String name4 = "1.0.2 Build S6B5";
check(name1);
check(name2);
check(name3);
check(name4);
}
private static void check(String name) {
Pattern p = Pattern.compile("(\\d+)\\.(\\d+)\\.(\\d+)\\s+Build\\s+([SDT]\\w{3,4})");
Matcher m = p.matcher(name);
if (m.find()) {
System.out.println("num1: " + m.group(1));
System.out.println("num2: " + m.group(2));
System.out.println("num3: " + m.group(3));
System.out.println("build: " + m.group(4));
} else {
System.out.println("not found");
}
}
Use Matcher.find() method to match parts of the test string and then Matcher.group() method to access the parts captured by the round brackets.
Resulting output:
not found
not found
not found
num1: 1
num2: 0
num3: 2
build: S6B5
Try this one instead :
(\d{1}).(\d{1}).(\d{1})\s(Build)\s([SDT])([\w\d]{3,4})
or
(\d).(\d).(\d)*\s(Build)\s([SDT])([\w\d]{3,4}) if you can have multiple numbers.
In your, the problem is the end of the regex : ".{3,4}". It means that you accept ANY character 3 to 4 times.

For Loop Depreciation Java [duplicate]

I was wondering if someone can show me how to use the format method for Java Strings.
For instance If I want the width of all my output to be the same
For instance, Suppose I always want my output to be the same
Name = Bob
Age = 27
Occupation = Student
Status = Single
In this example, all the output are neatly formatted under each other; How would I accomplish this with the format method.
System.out.println(String.format("%-20s= %s" , "label", "content" ));
Where %s is a placeholder for you string.
The '-' makes the result left-justified.
20 is the width of the first string
The output looks like this:
label = content
As a reference I recommend Javadoc on formatter syntax
If you want a minimum of 4 characters, for instance,
System.out.println(String.format("%4d", 5));
// Results in " 5", minimum of 4 characters
To answer your updated question you can do
String[] lines = ("Name = Bob\n" +
"Age = 27\n" +
"Occupation = Student\n" +
"Status = Single").split("\n");
for (String line : lines) {
String[] parts = line.split(" = +");
System.out.printf("%-19s %s%n", parts[0] + " =", parts[1]);
}
prints
Name = Bob
Age = 27
Occupation = Student
Status = Single
EDIT: This is an extremely primitive answer but I can't delete it because it was accepted. See the answers below for a better solution though
Why not just generate a whitespace string dynamically to insert into the statement.
So if you want them all to start on the 50th character...
String key = "Name =";
String space = "";
for(int i; i<(50-key.length); i++)
{space = space + " ";}
String value = "Bob\n";
System.out.println(key+space+value);
Put all of that in a loop and initialize/set the "key" and "value" variables before each iteration and you're golden. I would also use the StringBuilder class too which is more efficient.
#Override
public String toString() {
return String.format("%15s /n %15d /n %15s /n %15s", name, age, Occupation, status);
}
For decimal values you can use DecimalFormat
import java.text.*;
public class DecimalFormatDemo {
static public void customFormat(String pattern, double value ) {
DecimalFormat myFormatter = new DecimalFormat(pattern);
String output = myFormatter.format(value);
System.out.println(value + " " + pattern + " " + output);
}
static public void main(String[] args) {
customFormat("###,###.###", 123456.789);
customFormat("###.##", 123456.789);
customFormat("000000.000", 123.78);
customFormat("$###,###.###", 12345.67);
}
}
and output will be:
123456.789 ###,###.### 123,456.789
123456.789 ###.## 123456.79
123.78 000000.000 000123.780
12345.67 $###,###.### $12,345.67
For more details look here:
http://docs.oracle.com/javase/tutorial/java/data/numberformat.html

Java output formatting for Strings

I was wondering if someone can show me how to use the format method for Java Strings.
For instance If I want the width of all my output to be the same
For instance, Suppose I always want my output to be the same
Name = Bob
Age = 27
Occupation = Student
Status = Single
In this example, all the output are neatly formatted under each other; How would I accomplish this with the format method.
System.out.println(String.format("%-20s= %s" , "label", "content" ));
Where %s is a placeholder for you string.
The '-' makes the result left-justified.
20 is the width of the first string
The output looks like this:
label = content
As a reference I recommend Javadoc on formatter syntax
If you want a minimum of 4 characters, for instance,
System.out.println(String.format("%4d", 5));
// Results in " 5", minimum of 4 characters
To answer your updated question you can do
String[] lines = ("Name = Bob\n" +
"Age = 27\n" +
"Occupation = Student\n" +
"Status = Single").split("\n");
for (String line : lines) {
String[] parts = line.split(" = +");
System.out.printf("%-19s %s%n", parts[0] + " =", parts[1]);
}
prints
Name = Bob
Age = 27
Occupation = Student
Status = Single
EDIT: This is an extremely primitive answer but I can't delete it because it was accepted. See the answers below for a better solution though
Why not just generate a whitespace string dynamically to insert into the statement.
So if you want them all to start on the 50th character...
String key = "Name =";
String space = "";
for(int i; i<(50-key.length); i++)
{space = space + " ";}
String value = "Bob\n";
System.out.println(key+space+value);
Put all of that in a loop and initialize/set the "key" and "value" variables before each iteration and you're golden. I would also use the StringBuilder class too which is more efficient.
#Override
public String toString() {
return String.format("%15s /n %15d /n %15s /n %15s", name, age, Occupation, status);
}
For decimal values you can use DecimalFormat
import java.text.*;
public class DecimalFormatDemo {
static public void customFormat(String pattern, double value ) {
DecimalFormat myFormatter = new DecimalFormat(pattern);
String output = myFormatter.format(value);
System.out.println(value + " " + pattern + " " + output);
}
static public void main(String[] args) {
customFormat("###,###.###", 123456.789);
customFormat("###.##", 123456.789);
customFormat("000000.000", 123.78);
customFormat("$###,###.###", 12345.67);
}
}
and output will be:
123456.789 ###,###.### 123,456.789
123456.789 ###.## 123456.79
123.78 000000.000 000123.780
12345.67 $###,###.### $12,345.67
For more details look here:
http://docs.oracle.com/javase/tutorial/java/data/numberformat.html

pattern match java: does not work

i am trying to find a certain tag in a html-page with java. all i know is what kind of tag (div, span ...) and the id ... i dunno how it looks, how many whitespaces are where or what else is in the tag ... so i thought about using pattern matching and i have the following code:
// <tag[any character may be there or not]id="myid"[any character may be there or not]>
String str1 = "<" + Tag + "[.*]" + "id=\"" + search + "\"[.*]>";
// <tag[any character may be there or not]id="myid"[any character may be there or not]/>
String str2 = "<" + Tag + "[.*]" + "id=\"" + search + "\"[.*]/>";
Pattern p1 = Pattern.compile( str1 );
Pattern p2 = Pattern.compile( str2 );
Matcher m1 = p1.matcher( content );
Matcher m2 = p2.matcher( content );
int start = -1;
int stop = -1;
String Anfangsmarkierung = null;
int whichMatch = -1;
while( m1.find() == true || m2.find() == true ){
if( m1.find() ){
//System.out.println( " ... " + m1.group() );
start = m1.start();
//ende = m1.end();
stop = content.indexOf( "<", start );
whichMatch = 1;
}
else{
//System.out.println( " ... " + m2.group() );
start = m2.start();
stop = m2.end();
whichMatch = 2;
}
}
but i get an exception with m1(m2).start(), when i enter the actual tag without the [.*] and i dun get anything when i enter the regular expression :( ... i really havent found an explanation for this ... i havent worked with pattern or match at all yet, so i am a little lost and havent found anything so far. would be awesome if anyone could explain me what i am doing wrong or how i can do it better ...
thnx in advance :)
... dg
I know that I am broadening your question, but I think that using a dedicated library for parsing HTML documents (such as: http://htmlparser.sourceforge.net/) will be much more easier and accurate than regexps.
Here is an example for what you're trying to do adapted from one of my notes:
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Main {
public static void main(String[] args) {
String tag = "thetag";
String id = "foo";
String content = "<tag1>\n"+
"<thetag name=\"Tag Name\" id=\"foo\">Some text</thetag>\n" +
"<thetag name=\"AnotherTag\" id=\"foo\">Some more text</thetag>\n" +
"</tag1>";
String patternString = "<" + tag + ".*?name=\"(.*?)\".*?id=\"" + id + "\".*?>";
System.out.println("Content:\n" + content);
System.out.println("Pattern: " + patternString);
Pattern pattern = Pattern.compile(patternString);
Matcher matcher = pattern.matcher(content);
boolean found = false;
while (matcher.find()) {
System.out.format("I found the text \"%s\" starting at " +
"index %d and ending at index %d.%n",
matcher.group(), matcher.start(), matcher.end());
System.out.println("Name: " + matcher.group(1));
found = true;
}
if (!found) {
System.out.println("No match found.");
}
}
}
You'll notice that the pattern string becomes something like <thetag.*?name="(.*?)".*?id="foo".*?> which will search for tags named thetag where the id attribute is set to "foo".
Note the following:
It uses .*? to weakly match zero or more of anything (if you don't understand, try removing the ? to see what I mean).
It uses a submatch expression between parenthesis (the name="(.*?)" part) to extract the contents of the name attribute (as an example).
I think each call to find is advancing through your match. Calling m1.find() inside your condition is moving your matcher to a place where there is no longer a valid match, which causes m1.start() to throw (I'm guessing) an IllegalStateException Ensuring you call find once per iteration and referencing that result from some flag avoids this problem.
boolean m1Matched = m1.find()
boolean m2Matched = m2.find()
while( m1Matched || m2Matched ) {
if( m1Matched ){
...
}
m1Matched = m1.find();
m2Matched = m2.find();
}

Categories

Resources