contains() method without prefix and suffix in Java - java

I'm stuck on a (simple, I think) String validation. I use the following method to get a text from an EditText which can have 420 chars and must to contain a specific word (whatever its place):
if(edittext.getText().toString().toLowerCase().contains(stringToHave)) { }
// stringToHave = the specific String
However, I want to improve this condition. For example, you have this:
String a = "This not a MetaStackOverflow question";
String b = "stackoverflow";
And you want to know if a contains b regardless is case sensitive, then, you do as follows:
if(a.toLowerCase().contains(b)) { }
This condition is true because indeed a contains StackOverflow. However, a doesn't contain exactly b, there is a prefix as Meta. And this is not exactly the same word.. I tried to find a way on SO and on other Java websites without result.
How can I improve contains() method to find only the exact String without prefix or suffix? Should I use another method (as containsOnly(), I already tried it but it seems that is undefined for String, it's to check if it contains numeric/alphabetic/etc. chars)?
EDIT:
Add a "two spaces" verification is very attractive and ingenious. However, if the specific text is at the end of the sentence and we add a . this will not work, isn't it?
a = "This is great. This is on StackOverflow." // false because we have "."

You can use regex here. Matcher class has a find() method, which searches for a pattern in a string. This will work:
Matcher matcher = Pattern.compile("(?i)\\b" + Pattern.quote(b) + "\\b").matcher(a);
if (matcher.find()) {
// contains
}
(?i) is case-insensitive embedded flag. Pattern.quote() is used to escape the regex meta-characters if any in the search string.

Use space before and after the pattern what you seek:
if(a.toLowerCase().contains(" " + b + " ")) { }

You can use a case insensitive Pattern with word boundaries \\b to do this:
String a = "This not a MetaStackOverflow question";
String b = "stackoverflow";
Pattern p = Pattern.compile("\\b" + b + "\\b", Pattern.CASE_INSENSITIVE);
if (p.matcher(a).find()) { }

Related

Regular expression with URL Encoded Strings

I have strings that contain URL encoding (%22) and other characters [!##$%^&*]. I need to use a RegEx to check if the string contains a character within that group but exclude the URL encoded quote (%22). I can't get the negative look ahead to work properly nor am I able to get an excluded string (or negation) working either. Can someone help? Here is code so far that doesn't work:
Pattern p = Pattern.compile("[!##$%^&*]"); //
String[] tokens = {"%22Hobo%22", "Shoe*", "Rail%6Road","Sugar"};
for (String string : tokens) {
Matcher m = p.matcher(string);
boolean b = m.find()
System.out.println(string + ": " + b);
}
The desired output should be false, true, true, false.
(?!%22)[!##$%^&*]
Try this.See demo.
https://regex101.com/r/mS3tQ7/16
export const uriParser = (x) =>
//replace/regex exclude-negated [set-of-tokens], doesn't work/parse for (%[A-Fa-f0-9]{2})+
//decodeURI() does the same I believe, but this will always return a string,
//without an error object
//a-z or A-Z includes underscore '_' but not space whitespace, nor (\r\n|\r|\n)+
x.replace(/(%[A-Fa-f0-9]{2})+[^a-zA-Z0-9-+ ]+/g, "_");
https://www.ietf.org/rfc/rfc3986.txt#:~:text=2.4.%20%20When%20to%20Encode%20or%20Decode%0A
for my purposes I make my uri link fragmens go thru (%[A-Fa-f0-9]{2})+ on mount so I use .replace("_"," ") for ui but uriParser() for outgoing links in ux to bypass redundancy as much as possible. The use case choice is between getting a string always & putting specifications for other characters before this. "Whyo you do not use a URLEncoder?" – Jens' comment on question

Finding out what .* inside a regex matched?

Hey guys i have a new problem.
I have a dynamically created String, that contains a placeholder !fruit!. I then want to find any Strings that match this String. Therefore i do the following:
String s = "A Basket of !fruit! was lost";
String toCompare "A Basket of Apples was lost";
if (toCompare.match(s.replace("!fruit!", ".*"))) //Yes everycharacter is a Fruit :-P
//do something
I now want to know what the .* matched against (in this case "Apples") and i am kinda clueless on how to go about this...
You can make it a capturing group ((.*)), and use the Pattern API to get the group from the found match:
String s = "A Basket of !fruit! was lost";
String toCompare = "A Basket of Apples was lost";
Pattern pattern = Pattern.compile(s.replace("!fruit!", "(.*)"));
Matcher matcher = pattern.matcher(toCompare);
if (matcher.find()) {
System.out.println(matcher.group(1));
}
Firstly, you need the regex to define a capturing group, which is done with parenthesis: s.replace("!fruit!", "(.*)").
Then, you need to use a Pattern and Matcher instead of just the plain String.match.
Pattern pattern = Pattern.compile(s.replace("!fruit!", "(.*)"));
Matcher m = pattern.matcher(toCompare);
if (m.matches()) {
String fruit = m.group(1);
}
To be a bit more robust, you should also watch out for s strings that themselves have "special" regular expression characters, or don't contain "!fruit!" at all.
For instance, what if s = "Was a basket (or something) of !fruit! lost?". In that case, the first matching group will be of (or something), the parentheses won't be matched against (since they're special characters in regexes), and the ? will affect the t rather than matching a question mark. This would match:
toCompare = "Was a basket or something of apples los";
... with matcher.group(1) being "or something", rather than "apples" (which will be in matcher.group(2)).
Solving this problem generally is going to be just a bit harder. You should basically split the string on !fruit!, use Pattern.quote on each side, and then splice in a "(.*)". (Pattern.quote takes a string and returns a string which, when treated as a regular expression, will match the first string literally. For instance, passing in "foo?" will return `"foo\?".)
String[] splits = s.split("!fruit!");
if (splits.length != 2) {
throw new IllegalArgumentException("no '!fruit!' specified");
}
Pattern pattern = Pattern.compile(
Pattern.quote(splits[0]) + "(.*)" + Pattern.quote(splits[1]));
...

Replacing only the first space in a string

I want to replace the first space character in a string with another string listed below. The word may contain many spaces but only the first space needs to be replaced. I tried the regex below but it didn't work ...
Pattern inputSpace = Pattern.compile("^\\s", Pattern.MULTILINE);
String spaceText = "This split ";
System.out.println(inputSpace.matcher(spaceText).replaceAll(" "));
EDIT:: It is an external API that I am using and I have the constraint that I can only use "replaceAll" ..
Your code doesn't work because it doesn't account for the characters between the start of the string and the white-space.
Change your code to:
Pattern inputSpace = Pattern.compile("^([^\\s]*)\\s", Pattern.MULTILINE);
String spaceText = "This split ";
System.out.println(inputSpace.matcher(spaceText).replaceAll("$1 "));
Explanation:
[^...] is to match characters that don't match the supplied characters or character classes (\\s is a character class).
So, [^\\s]* is zero-or-more non-white-space characters. It's surrounded by () for the below.
$1 is the first thing that appears in ().
Java regex reference.
The preferred way, however, would be to use replaceFirst: (although this doesn't seem to conform to your requirements)
String spaceText = "This split ";
spaceText = spaceText.replaceFirst("\\s", " ");
You can use the String.replaceFirst() method to replace the first occurence of the pattern
System.out.println(" all test".replaceFirst("\\s", "test"));
And String.replaceFirst() internally calls Matcher.replaceFirst() so its equivalent to
Pattern inputSpace = Pattern.compile("\\s", Pattern.MULTILINE);
String spaceText = "This split ";
System.out.println(inputSpace.matcher(spaceText).replaceFirst(" "));
Do in 2 steps:
indexOf(" ") will tell you where is the index
result = str.substring(0, index) + str.substring(index+1, str.length())
The idea is this, you may need to adjust the index values properly according to API.
It should be faster than regexp, because there is 2x arraycopy and not need to text compile pattern matching and stuff.
Can use Apache StringUtils:
import org.apache.commons.lang.StringUtils;
public class substituteFirstOccurrence{
public static void main(String[] args){
String text = "Word1 Word2 Word3";
System.out.println(StringUtils.replaceOnce(text, " ", "-"));
// output: "Word1-Word2 Word3"
}
}
We can simply use yourString.replaceFirst(" ", ""); in Kotlin.

Java how can remove everything between two substring in a string

I want to remove any substring(s) in a string that begins with 'galery' and ends with 'jssdk));'
For instance, consider the following string:
Galery something something.... jssdk));
I need an algorithm that removes 'something something....' and returns 'Galery jssdk));'
This is what I've done, but it does not work.
newsValues[1].replaceAll("Galery.*?jssdK));", "");
Could probably be improved, I've done it fast:
public static String replaceMatching(String input, String lowerBound, String upperBound{
Pattern p = Pattern.compile(".*?"+lowerBound+"(.*?)"+upperBound+".*?");
Matcher m = p.matcher(input);
String textToRemove = "";
while(m.find()){
textToRemove = m.group(1);
}
return input.replace(textToRemove, "");
}
UPDATE Thx for accepting the answer, but here is a smaller reviewed version:
public static String replaceMatching2(String input, String lowerBound, String upperBound){
String result = input.replaceAll("(.*?"+lowerBound + ")" + "(.*?)" + "(" + upperBound + ".*)", "$1$3");
return result;
}
The idea is pretty simple actually, split the String into 3 groups, and replace those 3 groups with the first and third, droping the second one.
You are almost there, but that will remove the entire string. If you want to remove anything between Galery and jssdK));, you will have to do something like so:
String newStr = newsValues[1].replaceAll("(Galery)(.*?)(jssdK\\)\\);)","$1$3");
This will put the strings into groups and will then use these groups to replace the entire string. Note that in regex syntax, the ) is a special character so it needs to be escaped.
String str = "GaleryABCDEFGjssdK));";
String newStr = str.replaceAll("(Galery)(.*?)(jssdK\\)\\);)","$1$3");
System.out.println(newStr);
This yields: GaleryjssdK));
I know that the solution presented by #amit is simpler, however, I thought it would be a good idea to show you a useful way in which you can use the replaceAll method.
Simplest solution will be to replace the string with just the "edges", effectively "removing" 1 everything between them.
newsValues[1].replaceAll("Galery.*?jssdK));", "GaleryjssdK));");
1: I used "" here because it is not exactly replacing - remember strings are immutable, so it is creating a new object, without the "removed" part.
newsValues[1] = newsValues[1].substring(0,6)+newsValues.substring(newsValues[1].length()-5,newsValues[1].length())
This basically concatenates the "Galery" and the "jssdk" leaving or ignoring everything else. More importantantly, you can simply assign newValues[1] = "Galeryjssdk"

String Pattern Matching In Java

I want to search for a given string pattern in an input sting.
For Eg.
String URL = "https://localhost:8080/sbs/01.00/sip/dreamworks/v/01.00/cui/print/$fwVer/{$fwVer}/$lang/en/$model/{$model}/$region/us/$imageBg/{$imageBg}/$imageH/{$imageH}/$imageSz/{$imageSz}/$imageW/{$imageW}/movie/Kung_Fu_Panda_two/categories/3D_Pix/item/{item}/_back/2?$uniqueID={$uniqueID}"
Now I need to search whether the string URL contains "/{item}/". Please help me.
This is an example. Actually I need is check whether the URL contains a string matching "/{a-zA-Z0-9}/"
You can use the Pattern class for this. If you want to match only word characters inside the {} then you can use the following regex. \w is a shorthand for [a-zA-Z0-9_]. If you are ok with _ then use \w or else use [a-zA-Z0-9].
String URL = "https://localhost:8080/sbs/01.00/sip/dreamworks/v/01.00/cui/print/$fwVer/{$fwVer}/$lang/en/$model/{$model}/$region/us/$imageBg/{$imageBg}/$imageH/{$imageH}/$imageSz/{$imageSz}/$imageW/{$imageW}/movie/Kung_Fu_Panda_two/categories/3D_Pix/item/{item}/_back/2?$uniqueID={$uniqueID}";
Pattern pattern = Pattern.compile("/\\{\\w+\\}/");
Matcher matcher = pattern.matcher(URL);
if (matcher.find()) {
System.out.println(matcher.group(0)); //prints /{item}/
} else {
System.out.println("Match not found");
}
That's just a matter of String.contains:
if (input.contains("{item}"))
If you need to know where it occurs, you can use indexOf:
int index = input.indexOf("{item}");
if (index != -1) // -1 means "not found"
{
...
}
That's fine for matching exact strings - if you need real patterns (e.g. "three digits followed by at most 2 letters A-C") then you should look into regular expressions.
EDIT: Okay, it sounds like you do want regular expressions. You might want something like this:
private static final Pattern URL_PATTERN =
Pattern.compile("/\\{[a-zA-Z0-9]+\\}/");
...
if (URL_PATTERN.matcher(input).find())
If you want to check if some string is present in another string, use something like String.contains
If you want to check if some pattern is present in a string, append and prepend the pattern with '.*'. The result will accept strings that contain the pattern.
Example: Suppose you have some regex a(b|c) that checks if a string matches ab or ac
.*(a(b|c)).* will check if a string contains a ab or ac.
A disadvantage of this method is that it will not give you the location of the match, you can use java.util.Mather.find() if you need the position of the match.
You can do it using string.indexOf("{item}"). If the result is greater than -1 {item} is in the string

Categories