I am working on a command based feature for a project in Java and am having trouble when introducing arguments to these commands.
For example all the commands are stored like this this:
"Hey tell [USER] to [ACTION]"
Now when the user submits their command it will look like this:
"Hey tell Player to come see me"
Now I need to know how I can compare the users inputted command to the stored command containing placeholder values. I need to be able to compare the two strings and recognise that they are the same command and then from this extract the data [USER] and [ACTION] and return them as an array
array[0] = "Player"
array[1] = "come see me"
Really hope somebody can help me out, thanks
You can use Pattern Matching as below:
String command = "Hey tell [USER] to [ACTION]";
String input = "Hey tell Player to come see me";
String[] userInputArray = new String[2];
String patternTemplate = command.replace("[USER]", "(.*)");
patternTemplate = patternTemplate.replace("[ACTION]", "(.*)");
Pattern pattern = Pattern.compile(patternTemplate);
Matcher matcher = pattern.matcher(input);
if (matcher.matches()) {
userInputArray[0] = matcher.group(1);
userInputArray[1] = matcher.group(2);
}
In case you do not need a stored String like "Hey tell [USER] to [ACTION]" and you can use Java (java.util.regex) Pattern and Matcher.
This is an example:
Pattern p = Pattern.compile("Hey tell ([a-zA-z]+) to (.+)");
List<Pattern> listOfCommandPattern = new ArrayList<>();
listOfCommandPattern.add(p);
Example, parse the command:
String user;
String command;
Matcher m;
// for every command
for(Pattern p : listOfCommandPattern){
m = p.matcher(inputCommand);
if (m.matches()) {
user = m.group(1);
command = m.group(2);
break; // found user and command
}
}
Here is a slightly more general version:
String pattern = "Hey tell [USER] to [ACTION]";
String line = "Hey tell Player to come see me";
/* a regular expression matching bracket expressions */
java.util.regex.Pattern bracket_regexp = Pattern.compile("\\[[^]]*\\]");
/* how many bracket expressions are in "pattern"? */
int count = bracket_regexp.split(" " + pattern + " ").length - 1;
/* allocate a result array big enough */
String[] result = new String[count];
/* convert "pattern" into a regular expression */
String regex_pattern = bracket_regexp.matcher(pattern).replaceAll("(.*)");
java.util.regex.Pattern line_regex = Pattern.compile(regex_pattern);
/* match "line" */
if (line_regex.matcher(line).matches()) {
/* extract the matched strings */
for (int i=0; i<count; ++i) {
result[i] = line_matcher.group(i+1);
System.out.println(result[i]);
}
} else {
System.out.println("Doesn't match.");
}
Related
I'm working on a simple bot for discord and the first pattern reading works fine and I get the results I'm looking for, but the second one doesn't seem to work and I can't figure out why.
Any help would be appreciated
public void onMessageReceived(MessageReceivedEvent event) {
if (event.getMessage().getContent().startsWith("!")) {
String output, newUrl;
String word, strippedWord;
String url = "http://jisho.org/api/v1/search/words?keyword=";
Pattern reading;
Matcher matcher;
word = event.getMessage().getContent();
strippedWord = word.replace("!", "");
newUrl = url + strippedWord;
//Output contains the raw text from jisho
output = getUrlContents(newUrl);
//Searching through the raw text to pull out the first "reading: "
reading = Pattern.compile("\"reading\":\"(.*?)\"");
matcher = reading.matcher(output);
//Searching through the raw text to pull out the first "english_definitions: "
Pattern def = Pattern.compile("\"english_definitions\":[\"(.*?)]");
Matcher matcher2 = def.matcher(output);
event.getTextChannel().sendMessage(matcher2.toString());
if (matcher.find() && matcher2.find()) {
event.getTextChannel().sendMessage("Reading: "+matcher.group(1)).queue();
event.getTextChannel().sendMessage("Definition: "+matcher2.group(1)).queue();
}
else {
event.getTextChannel().sendMessage("Word not found").queue();
}
}
}
You had to escape the [ character to \\[ (once for the Java String and once for the Regex). You also did forget the closing \".
the correct pattern looks like this:
Pattern def = Pattern.compile("\"english_definitions\":\\[\"(.*?)\"]");
At the output, you might want to readd \" and start/end.
event.getTextChannel().sendMessage("Definition: \""+matcher2.group(1) + "\"").queue();
I know there are similar questions regarding to this. However, I tried many solutions and it just does not work for me.
I need help to extract multiple substrings from a string:
String content = "Ben Conan General Manager 90010021 benconan#gmail.com";
Note: The content in the String may not be always in this format, it may be all jumbled up.
I want to extract the phone number and email like below:
1. 90010021
2. benconan#gmail.com
In my project, I was trying to get this result and then display it into 2 different EditText.
I have tried using pattern and matcher class but it did not work.
I can provide my codes here if requested, please help me ~
--------------------EDIT---------------------
Below is my current method which only take out the email address:
private static final String EMAIL_PATTERN =
"[a-zA-Z0-9\\+\\.\\_\\%\\-\\+]{1,256}" +
"\\#" +
"[a-zA-Z0-9][a-zA-Z0-9\\-]{0,64}" +
"(" +
"\\." +
"[a-zA-Z0-9][a-zA-Z0-9\\-]{0,25}" +
")+";
public String EmailValidator(String email) {
Pattern pattern = Pattern.compile(EMAIL_PATTERN);
Matcher matcher = pattern.matcher(email);
if (matcher.find()) {
return email.substring(matcher.start(), matcher.end());
} else {
// TODO handle condition when input doesn't have an email address
}
return email;
}
You can separate your string into arraylist like this
String str = "Ben Conan, General Manager, 90010021, benconan#gmail.com";
List<String> List = Arrays.asList(str.split(" "));
maybe you should do this instead of yours :
String[] Stringnames = new String[5]
Stringnames [0] = "your phonenumber"
Stringnames[1] = "your email"
System.out.println(stringnames)
Or :
String[] Stringnames = new String[2]
String[] Stringnames = {"yournumber","your phonenumber"};
System.out.println(stringnames [1]);
String.split(...) is a java method for that.
EXAMPLE:
String content = "Ben Conan, General Manager, 90010021, benconan#gmail.com";
String[] selection = content.split(",");
System.out.println(selection[0]);
System.out.println(selection[3]);
BUT if you want to do a Regex then take a look at this:
https://stackoverflow.com/a/16053961/982161
Try this regex for phone number
[\d+]{8} ---> 8 represents number of digits in phone number
You can use
[\d+]{8,} ---> if you want the number of more than 8 digits
Use appropriate JAVA functions for matching. You can try the results here
http://regexr.com/
For email, it depends whether the format is simple or complicated. There is a good explanation here
http://www.regular-expressions.info/index.html
I have a rather complex (to me it seems rather complex) problem that I'm using regular expressions in Java for:
I can get any text string that must be of the format:
M:<some text>:D:<either a url or string>:C:<some more text>:Q:<a number>
I started with a regular expression for extracting the text between the M:/:D:/:C:/:Q: as:
String pattern2 = "(M:|:D:|:C:|:Q:.*?)([a-zA-Z_\\.0-9]+)";
And that works fine if the <either a url or string> is just an alphanumeric string. But it all falls apart when the embedded string is a url of the format:
tcp://someurl.something:port
Can anyone help me adjust the above reg exp to extract the text after :D: to be either a url or a alpha-numeric string?
Here's an example:
public static void main(String[] args) {
String name = "M:myString1:D:tcp://someurl.com:8989:C:myString2:Q:1";
boolean matchFound = false;
ArrayList<String> values = new ArrayList<>();
String pattern2 = "(M:|:D:|:C:|:Q:.*?)([a-zA-Z_\\.0-9]+)";
Matcher m3 = Pattern.compile(pattern2).matcher(name);
while (m3.find()) {
matchFound = true;
String m = m3.group(2);
System.out.println("regex found match: " + m);
values.add(m);
}
}
In the above example, my results would be:
myString1
tcp://someurl.com:8989
myString2
1
And note that the Strings can be of variable length, alphanumeric, but allowing some characters (such as the url format with :// and/or . - characters
You mention that the format is constant:
M:<some text>:D:<either a url or string>:C:<some more text>:Q:<a number>
Capture groups can do this for you with the pattern:
"M:(.*):D:(.*):C:(.*):Q:(.*)"
Or you can do a String.split() with a pattern of "M:|:D:|:C:|:Q:". However, the split will return an empty element at the first index. Everything else will follow.
public static void main(String[] args) throws Exception {
System.out.println("Regex: ");
String data = "M:<some text>:D:tcp://someurl.something:port:C:<some more text>:Q:<a number>";
Matcher matcher = Pattern.compile("M:(.*):D:(.*):C:(.*):Q:(.*)").matcher(data);
if (matcher.matches()) {
for (int i = 1; i <= matcher.groupCount(); i++) {
System.out.println(matcher.group(i));
}
}
System.out.println();
System.out.println("String.split(): ");
String[] pieces = data.split("M:|:D:|:C:|:Q:");
for (String piece : pieces) {
System.out.println(piece);
}
}
Results:
Regex:
<some text>
tcp://someurl.something:port
<some more text>
<a number>
String.split():
<some text>
tcp://someurl.something:port
<some more text>
<a number>
To extract the URL/text part you don't need the regular expression. Use
int startPos = input.indexOf(":D:")+":D:".length();
int endPos = input.indexOf(":C:", startPos);
String urlOrText = input.substring(startPos, endPos);
Assuming you need to do some validation along with the parsing:
break the regex into different parts like this:
String m_regex = "[\\w.]+"; //in jsva a . in [] is just a plain dot
String url_regex = "."; //theres a bunch online, pick your favorite.
String d_regex = "(?:" + url_regex + "|\\p{Alnum}+)"; // url or a sequence of alphanumeric characters
String c_regex = "[\\w.]+"; //but i'm assuming you want this to be a bit more strictive. not sure.
String q_regex = "\\d+"; //what sort of number exactly? assuming any string of digits here
String regex = "M:(?<M>" + m_regex + "):"
+ "D:(?<D>" + d_regex + "):"
+ "C:(?<D>" + c_regex + "):"
+ "Q:(?<D>" + q_regex + ")";
Pattern p = Pattern.compile(regex);
Might be a good idea to keep the pattern as a static field somewhere and compile it in a static block so that the temporary regex strings don't overcrowd some class with basically useless fields.
Then you can retrieve each part by its name:
Matcher m = p.matcher( input );
if (m.matches()) {
String m_part = m.group( "M" );
...
String q_part = m.group( "Q" );
}
You can go even a step further by making a RegexGroup interface/objects where each implementing object represents a part of the regex which has a name and the actual regex. Though you definitely lose the simplicity makes it harder to understand it with a quick glance. (I wouldn't do this, just pointing out its possible and has its own benefits)
Hi, you can see my code below. I have some strings Country, rank and grank in my code, initially they will be null, but if regex is mached, it should change the value. But even if regex is matched it is not changing the value it is always null. If I remove all if statements and append the string it works fine, but if match is not found it is throwing an exception. Please let me know how can I check this in if logic.
System.err.println(content);
Pattern c = Pattern.compile("NAME=\"(.*)\" RANK");
Pattern r = Pattern.compile("\" RANK=\"(.*)\"");
Pattern gr = Pattern.compile("\" TEXT=\"(.*)\" SOURCE");
Matcher co = c.matcher(content);
Matcher ra = r.matcher(content);
Matcher gra = gr.matcher(content);
co.find();
ra.find();
gra.find();
String country = null;
String Rank = null;
String Grank = null;
if (co.matches()) {
country = co.group(1);
}
if (ra.matches()) {
Rank = ra.group(1);
}
if (gra.matches()) {
Grank = gra.group(1);
}
You have to escape a single \ - use double \\ then it should work.
Tried this?
while (co.find()) {
System.out.print("Start index: " + co.start());
System.out.print(" End index: " + co.end() + " ");
System.out.println(co.group());
}
Personally I can't make your program work with / without the if so it's not a problem of logic but just a problem that it doesn't match the string for me
So I changed it to get something working, maybe you can use it :)
String content = "NAME=\"salut\" RANK=\"pouet\" TEXT=\"text\" SOURCE";
System.out.println(content);
System.out.println(content.replaceAll(("NAME=\"(.*)\"\\sRANK=\"(.*)\"\\sTEXT=\"(.*)\" SOURCE"), "$1---$2---$3"));
Output
NAME="salut" RANK="pouet" TEXT="text" SOURCE
salut---pouet---text
I need to change somethign like this -> Hello, go here http://www.google.com for your ...
grab the link, and change it in a method i made, and replace it back into the string like this
-> Hello, go here http://www.yahoo.com for your...
Here is what i have so far:
if(Text.toLowerCase().contains("http://"))
{
// Do stuff
}
else if(Text.toLowerCase().contains("https://"))
{
// Do stuff
}
All i need to do is change the URL in the String to something different. The Url in the String will not always be http://www.google.com, so i can not just say replace("http://www.google.com","")
Use regex:
String oldUrl = text.replaceAll(".*(https?://)www((\\.\\w+)+).*", "www$2");
text = text.replaceAll("(https?://)www(\\.\\w+)+", "$1" + traslateUrl(oldUrl));
Note: code changed to meet extra requirements in comments below.
you can grab the link from the string using below code. I assumed the string will contain only .com domain
String input = "Hello, go here http://www.google.com";
Pattern pattern = Pattern.compile("http[s]{0,1}://www.[a-z-]*.com");
Matcher m = pattern.matcher(input);
while (m.find()) {
String str = m.group();
}
Have you tried something like:
s= s.replaceFirst("http:.+[ ]", new link);
This will find any word beginning with http up till the first white space and replace it with whatever you want
if you want to keep the link then you can do:
String oldURL;
if (s.contains("http")) {
String[] words = s.split(" ");
for (String word: words) {
if (word.contains("http")) {
oldURL = word;
break;
}
}
//then replace the url or whatever
}
You can try this
private String removeUrl(String commentstr)
{
String urlPattern = "((https?|ftp|gopher|telnet|file|Unsure|http):((//)|(\\\\))+[\\w\\d:##%/;$()~_?\\+-=\\\\\\.&]*)";
Pattern p = Pattern.compile(urlPattern,Pattern.CASE_INSENSITIVE);
Matcher m = p.matcher(commentstr);
int i = 0;
while (m.find()) {
commentstr = commentstr.replaceAll(m.group(i),"").trim();
i++;
}
return commentstr;
}