I have the following class.
public class TestStringRegex {
public static void main(String[] args) {
StringBuilder text = new StringBuilder("KALAKA");
String wordToFind = "KA";
Pattern word = Pattern.compile(wordToFind);
Matcher match = word.matcher(text);
while (match.find()) {
System.out.println(match.end());
text=text.insert(match.end(),"INSERT");
}
System.out.println(text);
}
Expecting output to be KAINSERTLAKAINSERT.
But getting KAINSERTLAKA.
Is matcher/insert works on the length of input text?How to get desired output.
If you want to do it using matcher use the overloaded method with int i.e. matcher.find(index). For some reason mathcher.find() is not working as given in docs. If you are curious you need to debug the code.
Just say like below
int end = 0;
while (match.find(end)) {
end = match.end();
System.out.println(end);
text=text.insert(end,"INSERT");
}
Better way of doing the same will be
public static void main(String[] args) {
System.out.println("KALAKA".replaceAll("KA", "$0INSERT"));
}
That's all the code you need to write.
Use matcher.find(int startIndex) instead of find(). And update startIndex after each match. Full code:
public static void main(String[] args) {
StringBuilder text = new StringBuilder("KALAKA");
String wordToFind = "KA";
Pattern word = Pattern.compile(wordToFind);
Matcher match = word.matcher(text);
int findIndex = 0;
while (match.find(findIndex)) {
int end = match.end();
findIndex = end;
text = text.insert(end, "INSERT");
}
System.out.println(text);
}
Each next find() starts at the end of previous match
This works fine..!!!
public static void main(String[] args) {
StringBuilder text = new StringBuilder("KALAKA");
String wordToFind = "KA";
Pattern word = Pattern.compile(wordToFind);
Matcher match = word.matcher(text);
int end = 0;
while (match.find(end)) {
end = match.end();
text=text.insert(match.end(),"INSERT");
}
System.out.println(text);
}
Related
I'm getting the URL(http://localhost:8080/CompanyServices/api/creators/2173) shown below from a HTTP Response header and I want to get the id after the creators which is 2173.
So, I deleted all non digits as shown below and got the following result : 80802173.
Is it a good approach to get the last 4 digits from the above set of digits?
One thing is that, this part localhost:8080 could change depending upon the server I deploy my application so I'm wondering if I should just grab something after creators/ ? If yes, then what is the best way to go about it?
public class GetLastFourIDs {
public static void main(String args[]){
String str = "http://localhost:8080/CompanyServices/api/creators/2173";
String replaceString=str.replaceAll("\\D+","");
System.out.println(replaceString);
}
}
You can use regex API e.g.
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Main {
public static void main(String[] args) {
String str = "http://localhost:8080/CompanyServices/api/creators/2173";
Pattern pattern = Pattern.compile("(creators/\\d+)");
Matcher matcher = pattern.matcher(str);
int value = 0;
if (matcher.find()) {
// Get e.g. `creators/2173` and split it on `/` then parse the second value to int
value = Integer.parseInt(matcher.group().split("/")[1]);
}
System.out.println(value);
}
}
Output:
2173
Non-regex solution:
public class Main {
public static void main(String[] args) {
String str = "http://localhost:8080/CompanyServices/api/creators/2173";
int index = str.indexOf("creators/");
int value = 0;
if (index != -1) {
value = Integer.parseInt(str.substring(index + "creators/".length()));
}
System.out.println(value);
}
}
Output:
2173
[Update]
Incorporating comment by Andreas as follows:
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Main {
public static void main(String[] args) {
String str = "http://localhost:8080/CompanyServices/api/creators/2173";
Pattern pattern = Pattern.compile("creators/(\\d+)");
Matcher matcher = pattern.matcher(str);
int value = 0;
if (matcher.find()) {
value = Integer.parseInt(matcher.group(1));
}
System.out.println(value);
}
}
Output:
2173
In this code, we remove the substring "luna" from email string using the .replaceFirst method. We are removing the characters in between + and #. But this happens only in the first instance because we used .replaceFirst. What if we wanted to target the second instance of + and # to remove "smith"?
Our output now is alice+#john+smith#steve+oliver# but we want alice+luna#john+#steve+oliver#
public class Main {
public static void main(String[] args) {
String email = "alice+luna#john+smith#steve+oliver#";
String newEmail = email.replaceFirst("\\+.*?#", "");
System.out.println(newEmail);
}
}
You can find the second + like so:
int firstPlus = email.indexOf('+');
int secondPlus = email.indexOf('+', firstPlus + 1);
(You need to handle the case that there aren't two +s to find, if necessary).
Then find the following #:
int at = email.indexOf('#', secondPlus);
Then stitch it back together:
String newEmail = email.substring(0, secondPlus + 1) + email.substring(at);
or
String newEmail2 = new StringBuilder(email).delete(secondPlus + 1, at).toString();
Ideone demo
Unfortunately Java doesn't have methods like replace second, replace third etc. You can either replaceAll (which will replace all occurences) OR invoce replaceFirst again on the already replaced string. That's basically replacing the second. If you want to replace ONLY the second - then you can do it with substrings or do a regex matcher and iterate on results.
public static void main(String[] args) {
String email = "alice+luna#john+smith#steve+oliver#";
String newEmail = email.replaceFirst("\\+.*?#", "");
newEmail = newEmail .replaceFirst("\\+.*?#", ""); //this replaces the second right? :)
newEmail = newEmail .replaceFirst("\\+.*?#", ""); // replace 3rd etc.
System.out.println(newEmail);
}
You can alternate value of parameter n in following replaceNth method to 2, 3 to perform exactly the same operation as that of replaceSecond or replaceThird. ( Note: this method can be applied in any other value of n. If nth pattern do not exist , it simply return given string ).
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Main {
public static String replaceNth(String str, int n, String regex, String replaceWith) {
Pattern p = Pattern.compile(regex);
Matcher m = p.matcher(str);
while (m.find()) {
n--;
if (n == 0) {
return str.substring(0,m.start() + 1)+ replaceWith + str.substring(m.end() - 1);
}
}
return str;
}
public static void main(String args[]) {
String email = "alice+luna#john+smith#steve+oliver#";
System.out.println(replaceNth(email, 2, "\\+.*?#", ""));
}
}
I think it is better to encapsulate this logic into separate method, where String and group position are arguments.
private static final Pattern PATTERN = Pattern.compile("([^+#]+)#");
private static String removeSubstringGroup(String str, int pos) {
Matcher matcher = PATTERN.matcher(str);
while (matcher.find()) {
if (pos-- == 0)
return str.substring(0, matcher.start()) + str.substring(matcher.end() - 1);
}
return str;
}
Additionally, you can add more methods, to simplify using this util; like removeFirst() or removeLast()
public static String removeFirst(String str) {
return removeSubstringGroup(str, 0);
}
public static String removeSecond(String str) {
return removeSubstringGroup(str, 1);
}
Demo:
String email = "alice+luna#john+smith#steve+oliver#";
System.out.println(email);
System.out.println(removeFirst(email));
System.out.println(removeSecond(email));
System.out.println(removeSubstringGroup(email, 2));
System.out.println(removeSubstringGroup(email, 3));
Output:
alice+luna#john+smith#steve+oliver#
alice+#john+smith#steve+oliver#
alice+luna#john+#steve+oliver#
alice+luna#john+smith#steve+#
alice+luna#john+smith#steve+oliver#
Ideone demo
Suppose i have a string "[cat]:|:[]:|:[dog]:|:[cow]:|:[]:|:[]:|:[monkey]" like this.
I am able to print [cat][dog][cow][monkey] from the above string.
How can i print something like this = [cat]:|:[dog]:|:[cow]:|:[monkey].
please help.
import java.util.regex.*;
public class RegexMain {
static final String PATTERN = "\\[([^]]+)\\]|\"[^\"]*\"";
static final Pattern CONTENT = Pattern.compile(PATTERN);
public static void main(String[] args) {
String test1 = "[cat] [] [dog] [cow] [] [] [monkey]";
Matcher match = CONTENT.matcher(test1);
while(match.find()) {
if(match.group(1).length() != 0) {
System.out.print( match.group().trim());
}
}
}
}
I am actually not sure what your string is exactly (you are using different ones in your explanation and code). Anyways you can try this :
public static void main(String[] args) {
String s = "[cat]:|:[]:|:[dog]:|:[cow]:|:[]:|:[]:|:[monkey]";
System.out.println(s.replaceAll(":\\[\\]:\\|", ""));
}
O/P :
[cat]:|:[dog]:|:[cow]:|:[monkey]
how about
System.out.print( match.group().trim() + ":|:");
hey guys i have this id ABCD000000001XYZL
public class SmartCounter {
public String SmartCounter(String strID){
intNumber =Integer.parseInt(strID.replaceAll("\\D+",""));
intNumber += 1;
strReturn = "ABCD"+intNumber+"XYZL";
(strReturn);
}
}
Im just asking how can i add 1 to the Number part and return it into a string without loosing the zeros? TIA :D
Assuming the id is of the format
4 letters
9 numbers
4 letters
You can parse it using Regex, increment the number, then rebuild it. Something like this:
public static void main(String[] args) throws Exception {
final Pattern pattern = Pattern.compile("(\\D{4})(\\d{9})(\\D{4})");
final String input = "ABCD000000001XYZL";
final Matcher matcher = pattern.matcher(input);
if (matcher.matches()) {
final String head = matcher.group(1);
final long number = Long.parseLong(matcher.group(2)) + 1;
final String tail = matcher.group(3);
final String result = String.format("%s%09d%s", head, number, tail);
System.out.println(result);
}
}
You can use snazzier Regex and the Matcher.appendReplacement to make the code a little shorter; at the cost of complexity:
public static void main(String[] args) throws Exception {
final Pattern pattern = Pattern.compile("(?<=\\D{4})(\\d{9})(?=\\D{4})");
final String input = "ABCD000000001XYZL";
final Matcher matcher = pattern.matcher(input);
final StringBuffer result = new StringBuffer();
if (matcher.find()) {
final long number = Long.parseLong(matcher.group(1)) + 1;
matcher.appendReplacement(result, String.format("%09d", number));
}
matcher.appendTail(result);
System.out.println(result);
}
Have a look at DecimalFormat I'm sure you can figure out the details on your own
You could use String.format(String, Object...) and something like this,
class SmartCounter {
private int id = 1;
public SmartCounter() {
this.id = 1;
}
public SmartCounter(int id) {
this.id = id;
}
public String smartCounter() {
return String.format("ABCD%09dXYZL", id++);
}
}
Which you can run like
public static void main(String[] args) {
SmartCounter sc = new SmartCounter();
for (int i = 0; i < 3; i++) {
System.out.println(sc.smartCounter());
}
}
Output is
ABCD000000001XYZL
ABCD000000002XYZL
ABCD000000003XYZL
Let's say I have a String
String link = "www.thisisalink.com/tick1=#tick1#&tick2=#tick2#&tick3=#tick3#&tick4=#tick4#";
Then I can use
link = replaceFirst("(.+)=#\\1#", "");
To make it
link = "www.thisisalink.com/&tick2=#tick2#&tick3=#tick3#&tick4=#tick4#";
But I want to loop though the String, to get what has been replace and save it somewhere else, like a linked list or an array... result would be:
String[] result = ["tick1=#tick1#", "tick2=#tick2#", "tick3=#tick3#", "tick4=#tick4#"];
String link = "www.thisisalink.com/&&&";
But how can I do this? I tried looping with
while (link.matches("(.+)=#\\1#")){}
Which didn't work.
You can use Pattern Matcher classes to iterate over your string to find substrings that will match your regex. Then to replace founded substring you can use appednReplacement and appendTail. To get founded match you can use group() from Matcher instance.
Here is something similar to what you want
String link = "www.thisisalink.com/tick1=#tick1#&tick2=#tick2#&tick3=#tick3#&tick4=#tick4#";
StringBuffer sb = new StringBuffer();
Pattern p = Pattern.compile("(.+)=#\\1#");
Matcher m = p.matcher(link);
List<String> replaced = new ArrayList<>();
while (m.find()) {
m.appendReplacement(sb, "");
replaced.add(m.group());
}
m.appendTail(sb);
//to replace link with String stored in sb use link=sb.toString();
//otherwise link will be unchanged
System.out.println(sb);
System.out.println(replaced);
output:
www.thisisalink.com/&&&
[tick1=#tick1#, tick2=#tick2#, tick3=#tick3#, tick4=#tick4#]
This produces the Strings you want:
public static void main(String[] args)
{
final String link = "www.thisisalink.com/tick1=#tick1#&tick2=#tick2#&tick3=#tick3#&tick4=#tick4#";
final int index = link.indexOf("/") + 1;
final String[] result = link.substring(index).split("&");
final String newLink = link.substring(0, index) + repeat("&", result.length -1);
System.out.println(newLink);
for(final String tick : result)
{
System.out.println(tick);
}
}
private static String repeat(final String toRepeat, final int repetitions)
{
final StringBuilder sb = new StringBuilder(repetitions);
for(int i = 0; i < repetitions; i++)
{
sb.append(toRepeat);
}
return sb.toString();
}
Produces:
www.thisisalink.com/&&&
tick1=#tick1#
tick2=#tick2#
tick3=#tick3#
tick4=#tick4#