Regex grouping in Java - java

I'm looking to clean everything but the Class name off of a fully qualified Class name. So, I may have something like.....
"class gqlMain.Node"
... and I'd like to end up with....
"Node"
...I'm pretty sure my pattern...
"*.[\\.][^\\.]*"
..is correct, and when if simply run it as above and test with...
myMatcherObject.matches()
...it always returns true, but when I attempt to add groupings, like...
"(.*[\\.])([^\\.]*)"
...I always get a no match found error. Not sure what's going on.
ADDED:
Thanks for the quick responses, guys. Yeah, I really don't get this. My exact code is....
public String toString() {
Pattern packagePatt = Pattern.compile("(.*[\\.])([^\\.]*)");
//
System.out.println(this.compClass.getName().toString());
Matcher packageMatch = packagePatt.matcher(this.compClass.getName().toString());
//
System.out.println(packageMatch.group(2));
return packageMatch.group(2);
}
The first print statement produces a String like "gqlMain.Node", for example (I know the toString() is redundant, I added it out of exasperation). The second print statement produces an error, as would the return statement. With a debugger I can see that the groups List for the Matcher object remains empty at every index. But if I insert a...
if (packageMatcher.matches()) {
// print true
}
... I always get 'true'. This really makes no sense.

The following program reported "true":
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class so {
/**
* #param args
*/
public static void main(String[] args) {
Pattern p = Pattern.compile("(.*[\\.])([^\\.]*)");
Matcher m = p.matcher("class gqlMain.Node");
System.out.println(m.matches());
System.out.println(m.group(0));
System.out.println(m.group(1));
System.out.println(m.group(2));
}
}
The full output is:
true
class gqlMain.Node
class gqlMain.
Node

I wouldn't recommend to scan for the identifiers in that way (but I believe you wanted not to over-engineer), and you probably will like the following solution that is more strict for scanning the identifiers in general (however, speaking frankly, I don't believe I'm scanning for an identifier in the most correct way too). Additionally, it can scan for several fully/partially qualified identifiers within a single string, but it completely ignores non-qualified one (e.g. class is ambiguous).
package stackoverflow;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static java.lang.System.out;
import static java.util.regex.Pattern.CASE_INSENSITIVE;
import static java.util.regex.Pattern.compile;
public final class Q11554180 {
private Q11554180() {
}
//
// (3) The same as item (1) however we're ------------------------------------------------+
// capturing the group to get the class |
// name only |
// (2) At least one package name is required ---------------------------------+ |
// (1) We're searching valid package names only -----------------+ | |
// and we do not need to capture it ?: | | |
// +----------------+--------------+|+-------------+-------------+
// | ||| |
private static final Pattern pattern = compile("(?:[\\p{Alpha}_][\\p{Alnum}_]*\\.)+([\\p{Alpha}_][\\p{Alnum}_]*)", CASE_INSENSITIVE);
private static void find(CharSequence s) {
final Matcher matcher = pattern.matcher(s);
while ( matcher.find() ) {
out.println(matcher.group(1));
}
}
public static void main(String[] args) {
find("class gqlMain.Node; class gqlMain.p1.NodeA");
find("class gqlMain.p1.p11.NodeB");
find("class gqlMain.p1.p11.p111.NodeC");
find(Q11554180.class.getCanonicalName());
}
}
The code above will produce the following output:
Node
NodeA
NodeB
NodeC
Q11554180

Related

Regular expression works in test case but not in the real code

I have the following expression representing a playing card pattern:
String RCARD1 = "[CDHS]{1}\\:\\d{1,2}[1-14]";
when I test it in my test case it works as expected, here is the test case:
#Test
public void checkRegex() throws AssertionError {
System.out.println("Checking the correctness of card regular expressions");
String RCARD1 = "[CDHS]{1}\\:\\d{1,2}[1-14]";
String cardSymbol = "H:14";
assertTrue(cardSymbol.matches(RCARD1));
cardSymbol = "C:16";
assertFalse(cardSymbol.matches(RCARD1));
cardSymbol = "Z:5";
assertFalse(cardSymbol.matches(RCARD1));
}
However when I use this into the Card constructor it always returns false. The following code is slightly modified and I don't check the result, further decipher method works fine.
public Card(String cardSymbol) throws UnknownCardException {
boolean res = cardSymbol.matches(RCARD1); //fails here !!!
if (this.decypherCard(cardSymbol)) {
}
else throw new UnknownCardException();
}
So what's the problem here? Why it is not working?
The [1-14] character class matches 1 and 4 only. If you need to match numbers from 1 to 14, use (?:1[0-4]|0?[1-9]).
This regex should work then:
^[CDHS]:(?:1[0-4]|0?[1-9])$
See this demo.
NOTE: With String.matches(), you do not need ^ and $ (you may remove them from the pattern).

Finding specific text in txt file and storing it in String

first I want to say that I'm beginer and that this is my first Java program. I'd like to make a program that will read text file, find specific line, and save it to my string variable.
So I want to find line that starts with "Dealt to ", and then in that line, copy everything after that till this char '[' and put it in my string variable.
So let's say that I have this line in my text file:
Dealt to My NickName [text]
I want to have a program that will find text "My Nickname" and put it in my string variable.
I'm trying to work with classes and trying to use setters and getters just to practice, please let me know how my code looks like and how I can improve it and make it work.
this is Main.java:
import java.io.IOException;
public class Main {
public static void main(String[] args) throws IOException{
HandHistory hh1 = new HandHistory();
String hero1 = null;
hero1 = hh1.getHero();
System.out.println(hero1);
}
}
My HandHistory.java:
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class HandHistory {
private String hero;
public HandHistory(){}
public String getHero() throws IOException {
FileReader in = new FileReader("G:/Java/workspace/HandHistory/src/File.txt");
BufferedReader br = new BufferedReader(in);
String line;
while ((line = br.readLine()) != null) {
if (line.contains("Dealt to ")){
hero = line.substring(9,(line.indexOf("["))-1);
}
}
return hero;
}
public void setHero(String hero){
this.hero = hero;
}
}
It's a good start, good way to read a file line by line. The one problem worth fixing is closing the FileReader resource by using a try-finally block, or since Java 7 the new try-with-resources block:
try (FileReader in = new FileReader("G:/Java/workspace/HandHistory/src/File.txt")) {
...
}
Other tips and comments I can think of:
You don't have to have a setter in your class if you don't actually need it
Your code doesn't work will if there are lines contain the string "Dealt to" but don't start with that string. E.g. "Foobar Dealt to My NickName [text]" will still be matched but will return a wrong value
If you really only want to match lines that start with "Dealt to" then use String.startsWith() instead of String.contains()
You should handle the case when there's no "[" in the string, otherwise your code crashes with a hard to understand error
Regular expressions are useful if they remove complexity from your code. In your case the problem can be solved by using startsWith and indexOf relatively easily, so I'd not use RegExps in this case
It's not obvious what HandHistory.getHero() does without looking at the actual code. It's always very helpful even for yourself to assign names to things that express what the class or method is actually doing.
It can be said that getHero() method does too many things and so does the class HandHistory, but that's maybe something to consider when using the code for something bigger than a learning hello-world example.
My advise would be to use a Regex. You can try with
(?<=beginningstringname)(.*\n?)(?=endstringname)
So, for your problem this would be
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class RegexMatches
{
public static void main( String args[] ){
// String to be scanned to find the pattern.
String line = "Dealt to My NickName [text]";
String pattern = "(?<=Dealt to )(.*\n?)(?=[)";
// Create a Pattern object
Pattern r = Pattern.compile(pattern);
// Now create matcher object.
Matcher m = r.matcher(line);
//m now haves what you desire. You can loop it if you want.
if (m.find( )) {
System.out.println("Found value: " + m.group(0) );
System.out.println("Found value: " + m.group(1) );
System.out.println("Found value: " + m.group(2) );
} else {
System.out.println("NO MATCH");
}
}
}
Try this tutorial for using regular expressions in Java http://www.tutorialspoint.com/java/java_regular_expressions.htm

javac equivalent of "-D"?

Is there a way to give the java compiler some kind of variable that is accessible to the running java code?
In C/C++ I can give the compile -DKEY=VALUE and that would cause the preprocessor to have a #define for KEY equals to VALUE. I can then check this value in compile time to effect what code is being compiled.
I found java's -D, but that puts values give the the java command line in System.getProperty(). I want an argument give in compile time, not invocation time.
javac has the
-Akey[=value]
commandline option to pass information to annotation processors.
With java annotations it is possible to generate additional code on the fly, which can be configured on command line. It allow to produce more source code, configuration files, xml files, ... The main limitation is that you are allowed only to (re)generate new source files, you cannot modify existing ones.
Below is a short tutorial on how to allow from javac command specify parameters which will be visible in Java code. How usefull is that? Ie. you could specify a boolean option which would disable some parts of code, I am preety sure this parts of code could be removed using tools like proguard - or even optimized out by javac. Other uses is to specify new version number. Those use cases are mostly what c++ marcros are used for.
So, you need :
a dummy annotation class which will allow processor to run. It should be specified only once in your application.
a processor class which will run for above dummy annotation, and generate options class. It will also read options from javac command line.
a dummy Main class for testing purposes.
You will have to also compile your processor file before compiling Main class. This of course is done only when processor class is modified. All the three files are at the bottom. Now the compilation looks as follows (I am on windows):
Compile processor:
javac .\com\example\ConfigWritterAnnotationProcessor.java
Then Main.java with additional parameters to processor:
javac -processor com.example.ConfigWritterAnnotationProcessor -AtextToPrint="Hello World!" -AenablePrint=true ./com/example/Main.java
And thats all, now you may run Main.class and it will use Options class generated during compilation with above parameters set. It will look as follows:
package com.example;
public class Options {
public static final String textToPrint = "Hello World!";
public static final boolean enablePrint = true;
}
ProcessorStarterAnnotation.java
package com.example;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
#Target({ElementType.TYPE})
public #interface ProcessorStarterAnnotation {
}
Main.java
package com.example;
#ProcessorStarterAnnotation
public class Main {
public static void main(String[] args) {
if ( com.example.Options.enablePrint ) {
System.out.println(com.example.Options.textToPrint);
}
else {
System.out.println("Print disabled");
}
}
}
ConfigWritterAnnotationProcessor.java
package com.example;
import javax.annotation.processing.*;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
import javax.tools.Diagnostic;
import javax.tools.JavaFileObject;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Writer;
import java.util.Map;
import java.util.Set;
#SupportedAnnotationTypes("com.example.ProcessorStarterAnnotation")
#SupportedSourceVersion(SourceVersion.RELEASE_6)
#SupportedOptions({"textToPrint", "enablePrint"})
public class ConfigWritterAnnotationProcessor extends AbstractProcessor {
private Map<String,String> options;
#Override
public synchronized void init(ProcessingEnvironment processingEnv) {
super.init(processingEnv);
options = processingEnv.getOptions();
}
#Override
public boolean process(Set<? extends TypeElement> annotations,
RoundEnvironment currentRound) {
if (!currentRound.processingOver()) {
// This for-s are because processor is also run on newly created Options class.
for (TypeElement te : annotations) {
for (Element e : currentRound.getElementsAnnotatedWith(te)) {
try {
processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, "Creating com.example.Options");
JavaFileObject javaFile = processingEnv.getFiler().createSourceFile("com.example.Options");
Writer w = javaFile.openWriter();
try {
PrintWriter pw = new PrintWriter(w);
pw.println("package com.example;");
pw.println("public class Options {");
pw.println(" public static final String textToPrint = \"" + options.get("textToPrint") + "\";");
pw.println(" public static final boolean enablePrint = " + options.get("enablePrint") + ";");
pw.println("}");
pw.flush();
} finally {
w.close();
}
} catch (IOException x) {
processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR,
x.toString());
}
}
}
}
return false;
}
}
There is nothing like this in Java. Compile time constants must be declared in source code, and as far as I know, there is no pre-processor.
BTW, you could use flags given to java command line (-D args) to initialize java constants at runtime, that would mimic what you are looking for.
Ex:
class Foo {
private static final String BAR;
static {
String foobar = System.getProperty("foo.bar");
if(foobar != null && foobar.length()>0) {
BAR = foobar;
} else {
BAR = "somedefaultvalue";
}
}
}
Invoke with java Xxx -Dfoo.bar=foobar
As there is no notion of preprocessing in Java, a solution is to design your own.
One may think of using a standard C preprocessor or a custom-made one and compile the preprocessed output, but this has the disadvantage of duplicating the files, so that the project will become more complex, and the support from the development environment will degrade (like ability to jump to a syntax error).
My suggestion is to use annotations via comments that will guide a custom preprocessor and let it do substitutions before compiling.
For example,
public static void main(String[] args) {
int nDisks = 3;
doTowers(nDisks, 'A', 'B', 'C');
}
would become
public static void main(String[] args) {
int nDisks = /*#NDISKS*/ 3 /**/;
doTowers(nDisks, 'A', 'B', 'C');
}
Then your preprocessor would have a definition file such as
NDISKS 5
turning the code in
public static void main(String[] args) {
int nDisks = /*#NDISKS*/ 5 /**/;
doTowers(nDisks, 'A', 'B', 'C');
}
Similarly, you can emulate conditional code compilation with
doTowers(topN - 1, from, to, inter);
/*!PRINT*/
System.out.println("Disk "
+ topN + " from " + from + " to " + to);
/**/
doTowers(topN - 1, inter, from, to);
which could be turned by the preprocessor (with a definition like PRINT OFF) into
doTowers(topN - 1, from, to, inter);
/*!PRINT
System.out.println("Disk "
+ topN + " from " + from + " to " + to);
*/
doTowers(topN - 1, inter, from, to);
You can use alternative syntaxes, but the main ideas are
that the annotated code remains compilable,
that the preprocessor substitutions are reversible.
It would be against the design of the language to have it that way. What -DKEY=VALUE does is that it actually replaces KEY with VALUE in the source during preprocessor in C/C++.
Java does not have a preprocessor so that's mechanism is not available. If you want something "equivalent" you have to question what you mean by that. By not preprocessing the source it wouldn't be really equivalent.
If you on the other hand would like it to mean to set the value of the symbol KEY to the value VALUE you'd run into the problem that you would need to declare the symbol KEY anyway to determine it's type. In this case it would only be yet another constant/variable with the constraints that implies.
This means that even with such a feature it would not actually alter the generated code and you would hardly be better of than defining the value att launch time. That's why supplying the parameter via java would be the way to go.

How to use regular expression for fetching specific data?

I have input stream with the following data:
---------------------------------------------
manil#manil-ubvm:~$ db2level
DB21085I Instance "manil" uses "64" bits and DB2 code release "SQL10010" with
level identifier "0201010E".
Informational tokens are "DB2 v10.1.0.0", "s120403", "LINUXAMD64101", and Fix
Pack "0".
Product is installed at "/home/manil/sqllib".
---------------------------------------------
From above i need v10.1.0.0 to be stored in a string variable.
How to do that using java regular expression?
Use something like this to capture the version pattern :
import java.util.regex.*;
public class RTest {
public static void main(String [] args) {
String raw_data = "asdkgjasdbf984 sdkjfashfiu 4qwsadkfjnv w98sa-asdf08gywbfsd v1231.123.12.11.1 fkjsdfn9823isd";
Pattern version_find = Pattern.compile("v[\\d+\\.?]+");
Pattern directory_find = Pattern.compile("[\\/[^\\/]+]+");
Matcher version_finder = version_find.matcher(raw_data);
while(version_finder.find()) {
System.out.println(version_finder.group());
}
}
}
Output is :
v1231.123.12.11.1
/isd/asdasd2903 ajshdaq09r34/adsj 38/
You really need to understand regexes deeply if you are a programmer. They are one of the essentials. They are hard at first, but once you 'crack them' you don't forget it. Like riding a bike.
This will suit your needs:
String version = yourLine.replaceAll(".*(v\\d+([.]\\d+){3}).*", "$1")
You dont need regularExpression here
just use
String .contain() method and String substring()

Java Cut Links from shoutcast stream url

the string
[playlist]numberofentries=2File1=http://66.162.107.142/cpr1_K128OV.oggTitle1=KCFR NewsLength1=-1File2=http://66.162.107.141:8000/cpr1_K128OV.oggTitle2=KCFR News BackupLength2=-1Version=2
i wanna cut all of the links in this file, how to?
The following class
package regexpso;
import java.util.regex.*;
public class Main {
public static void main(String[] args) {
Pattern p = Pattern.compile("(http:.*?.ogg)");
Matcher m = p.matcher("[playlist]numberofentries=2File1=http://66.162.107.142/cpr1_K128OV.oggTitle1=KCFR NewsLength1=-1File2=http://66.162.107.141:8000/cpr1_K128OV.oggTitle2=KCFR News BackupLength2=-1Version=2");
while (m.find()) {
System.out.println(m.group());
}
}
}
prints
http://66.162.107.142/cpr1_K128OV.ogg
http://66.162.107.141:8000/cpr1_K128OV.ogg
as result.
Use a regular expression to find and replace the URLs. Be aware this sort of thing is fraught with peril. Post an example of what you want the end result to look like for a better answer. Are all the URLs IP addresses?

Categories

Resources