Replace a String between two Strings and Boundary words also [duplicate] - java

This question already has answers here:
Regex Match all characters between two strings
(16 answers)
Closed 13 days ago.
I want to replace string variable text between two words and replace the boundary words themselves.
Similar to this question, however I want to replace between &firstString and &endString
with newText .
Replace a String between two Strings
Input:
abcd&firstString={variableText}&endStringxyz
Output:
abcdnewTextxyz
I could just do two str.replaceAll(&firstString) and str.replaceAll(&secondString).
However, is it possible to do in one line of code changing maybe this code solution?
String newstr = str.replaceAll("(&firstString=)[^&]*(&endString=)", "$1foo$2");

String replacement = "newText";
String text = "abcd&firstString={currentText}&secondStringxyz";
String result = text.replaceAll("&firstString=\\{.*?\\}&secondString",replacement);
System.out.println(result);
prints
abcdnewTextxyz

The question is really confusing but I think I have got it based on the other answer.
You want to replace &firstString={XYZ}&endString with the value of a XYZ String variable?
First of all, in Java, one cannot reference a variable using a String that stores the variable name (Java is statically typed). To counteract this, you can have a HashMap that stores the 'variable' names as the keys and the replacement String as the value.
So, using your example we have:
String in = "abcd&firstString={variableText}&endStringxyz";
and you want to replace variableText with "newText".
So, we can do this:
Map<String, String> replacementMap = new HashMap<>(){{
put("variableText", "newText"); // replace "variableText" with "newText"
put("foo", "bar"); // replace "foo" with "bar"
}};
We can then declare a utility method for replacement (slightly modified code gotten from here):
private static final Pattern replaceTextPattern = Pattern.compile("&firstString=\\{.*?\\}&endString");
public static String replaceText(String input, Map<String, String> replacementMap){
StringBuilder sb = new StringBuilder();
Matcher matcher = replaceTextPattern.matcher(input);
while(matcher.find()){
String match = matcher.group();
String key = match.substring(
match.indexOf('{')+1,
match.lastIndexOf('}')
);
String replacement = replacementMap.get(key);
matcher.appendReplacement(sb, replacement);
}
matcher.appendTail(sb);
return sb.toString();
}
And finally call the method:
System.out.println(replaceText(in, replacementMap)); // abcdnewTextxyz
It even works with multiple variables:
System.out.println(replaceText("abcd&firstString={variableText}&endStringxyz&firstString={foo}&endStringdef", replacementMap)); // abcdnewTextxyzbardef

Related

Replace the opening and closing string, while keeping the enclosed value?

String value="==Hello==";
For the above string, I have to replace the "==" tags as <Heading>Hello</Heading>. I have tried doing it like this:
value = value.replaceAll("(?s)\\=\\=.","<heading>");
value = value.replaceAll(".\\=\\=(?s)","</heading>");
However, my original dataset is huge, with lots of strings like this to be replaced. Can the above be performed in a single statement, giving preference to performance?
The regex should not affect strings of form, ===<value>===, where value is any string of characters[a-z,A-Z].
To avoid iterating over string many times to first replace ===abc=== and then ==def== we can iterate over it once and thanks to Matehr#appendReplacement and Matcher#appendTail dynamically decide how to replace found match (based on amount of =).
Regex which can search find both described cases can look like: (={2,3})([a-z]+)\1 but to make it more usable lets use named groups (?<name>subregex) and also instead of [a-z] use more general [^=]+.
This will give us
Pattern p = Pattern.compile("(?<eqAmount>={2,3})(?<value>[^=]*)\\k<eqAmount>");
Group named eqAmount will hold == or ===. \\k<eqAmount> is backreference to that group, which means regex expects to find it also == or === depending on what eqAmount already holds.
Now we need some mapping between == or === and replacements. To hold such mapping we can use
Map<String,String> replacements = new HashMap<>();
replacements.put("===", "<subheading>${value}</subheading>");
replacements.put("==", "<heading>${value}</heading>");
${value} is reference to capturing group named value - here (?<value>[^=]*) so it will hold text between both == or ===.
Now lets see how it works:
String input = "===foo=== ==bar== ==baz== ===bam===";
Map<String, String> replacements = new HashMap<>();
replacements.put("===", "<subheading>${value}</subheading>");
replacements.put("==", "<heading>${value}</heading>");
Pattern p = Pattern.compile("(?<eqAmount>={2,3})(?<value>[^=]*)\\k<eqAmount>");
StringBuffer sb = new StringBuffer();
Matcher m = p.matcher(input);
while (m.find()) {
m.appendReplacement(sb, replacements.get(m.group("eqAmount")));
}
m.appendTail(sb);
String result = sb.toString();
System.out.println(result);
Output: <subheading>foo</subheading> <heading>bar</heading> <heading>baz</heading> <subheading>bam</subheading>
Try this:
public static void main(final String[] args) {
String value = "===Hello===";
value = value.replaceAll("===([^=]+)===", "<Heading>$1</Heading>");
System.out.println(value);
}

Android Java, replace each letter in a text [duplicate]

I have some strings with equations in the following format ((a+b)/(c+(d*e))).
I also have a text file that contains the names of each variable, e.g.:
a velocity
b distance
c time
etc...
What would be the best way for me to write code so that it plugs in velocity everywhere a occurs, and distance for b, and so on?
Don't use String#replaceAll in this case if there is slight chance part you will replace your string contains substring that you will want to replace later, like "distance" contains a and if you will want to replace a later with "velocity" you will end up with "disvelocityance".
It can be same problem as if you would like to replace A with B and B with A. For this kind of text manipulation you can use appendReplacement and appendTail from Matcher class. Here is example
String input = "((a+b)/(c+(d*e)))";
Map<String, String> replacementsMap = new HashMap<>();
replacementsMap.put("a", "velocity");
replacementsMap.put("b", "distance");
replacementsMap.put("c", "time");
StringBuffer sb = new StringBuffer();
Pattern p = Pattern.compile("\\b(a|b|c)\\b");
Matcher m = p.matcher(input);
while (m.find())
m.appendReplacement(sb, replacementsMap.get(m.group()));
m.appendTail(sb);
System.out.println(sb);
Output:
((velocity+distance)/(time+(d*e)))
This code will try to find each occurrence of a or b or c which isn't part of some word (it doesn't have any character before or after it - done with help of \b which represents word boundaries). appendReplacement is method which will append to StringBuffer text from last match (or from beginning if it is first match) but will replace found match with new word (I get replacement from Map). appendTail will put to StringBuilder text after last match.
Also to make this code more dynamic, regex should be generated automatically based on keys used in Map. You can use this code to do it
StringBuilder regexBuilder = new StringBuilder("\\b(");
for (String word:replacementsMap.keySet())
regexBuilder.append(Pattern.quote(word)).append('|');
regexBuilder.deleteCharAt(regexBuilder.length()-1);//lets remove last "|"
regexBuilder.append(")\\b");
String regex = regexBuilder.toString();
I'd make a hashMap mapping the variable names to the descriptions, then iterate through all the characters in the string and replace each occurrance of a recognised key with it's mapping.
I would use a StringBuilder to build up the new string.
Using a hashmap and iterating over the string as A Boschman suggested is one good solution.
Another solution would be to do what others have suggested and do a .replaceAll(); however, you would want to use a regular expression to specify that only the words matching the whole variable name and not a substring are replaced. A regex using word boundary '\b' matching will provide this solution.
String variable = "a";
String newVariable = "velocity";
str.replaceAll("\\b" + variable + "\\b", newVariable);
See http://docs.oracle.com/javase/tutorial/essential/regex/bounds.html
For string str, use the replaceAll() function:
str = str.toUpperCase(); //Prevent substitutions of characters in the middle of a word
str = str.replaceAll("A", "velocity");
str = str.replaceAll("B", "distance");
//etc.

Replace the last occurrence of a string in another string [duplicate]

This question already has answers here:
Replace the last part of a string
(11 answers)
Closed 8 years ago.
Let's say I have a string
string myWord="AAAAA";
I want to replace "AA" with "BB", but only the last occurrence, like so:
"AAABB"
Neither string.replace() nor string.replaceFirst() would do the job.
Is there a string.replaceLast()? And, If not, will there ever be one or is there an alternative also working with regexes?
Find the index of the last occurrence of the substring.
String myWord = "AAAAAasdas";
String toReplace = "AA";
String replacement = "BBB";
int start = myWord.lastIndexOf(toReplace);
Create a StringBuilder (you can just concatenate Strings if you wanted to).
StringBuilder builder = new StringBuilder();
Append the part before the last occurrence.
builder.append(myWord.substring(0, start));
Append the String you want to use as a replacement.
builder.append(replacement);
Append the part after the last occurrence from the original `String.
builder.append(myWord.substring(start + toReplace.length()));
And you're done.
System.out.println(builder);
You can do this:
myWord = myWord.replaceAll("AA$","BB");
$ means at the last.
Just get the last index and do an in place replacement of the expression with what you want to replace.
myWord is the original word sayAABDCAADEF. sourceWord is what you want to replace, say AA
targetWord is what you want to replace it with say BB.
StringBuilder strb=new StringBuilder(myWord);
int index=strb.lastIndexOf(sourceWord);
strb.replace(index,sourceWord.length()+index,targetWord);
return strb.toString();
This is useful when you want to just replace strings with Strings.A better way to do it is to use Pattern matcher and find the last matching index. Take as substring from that index, use the replace function there and then add it back to the original String. This will help you to replace regular expressions as well
String string = "AAAAA";
String reverse = new StringBuffer(string).reverse().toString();
reverse = reverse.replaceFirst(...) // you need to reverse needle and replacement string aswell!
string = new StringBuffer(reverse).reverse().toString();
It seems like there could be a regex answer to this.
I initially was trying to solve this through regex, but could not solve for situations like 'AAAzzA'.
So I came up with this answer below, which can handle both 'AAAAA' and 'AAAzzA'. This may not be the best answer, but I guess it works.
The basic idea is to find the last index of 'AA' occurrence and split string by that index:
String myWord = "AAAAAzzA";
String source = "AA";
String target = "BB";
int lastIndex = -1;
if ((lastIndex = myWord.lastIndexOf(source)) >= 0) {
String f = myWord.substring(0, lastIndex);
String b = myWord.substring(lastIndex + target.length() >= myWord
.length() ? myWord.length() : lastIndex + target.length(),
myWord.length());
myWord = f + target + b;
}
System.out.println(myWord);
myWord=myWord.replaceAll("AA(?!A)","BB");
You can do this with String#subtring
myWord= myWord.substring(0, myWord.length() - 2) + "BB";

how to check if string contains '+' character [duplicate]

This question already has answers here:
How can I check if a single character appears in a string?
(16 answers)
Closed 6 years ago.
I want to check if my string contains a + character.I tried following code
s= "ddjdjdj+kfkfkf";
if(s.contains ("\\+"){
String parts[] = s.split("\\+);
s= parts[0]; // i want to strip part after +
}
but it doesnot give expected result.Any idea?
You need this instead:
if(s.contains("+"))
contains() method of String class does not take regular expression as a parameter, it takes normal text.
EDIT:
String s = "ddjdjdj+kfkfkf";
if(s.contains("+"))
{
String parts[] = s.split("\\+");
System.out.print(parts[0]);
}
OUTPUT:
ddjdjdj
Why not just:
int plusIndex = s.indexOf("+");
if (plusIndex != -1) {
String before = s.substring(0, plusIndex);
// Use before
}
It's not really clear why your original version didn't work, but then you didn't say what actually happened. If you want to split not using regular expressions, I'd personally use Guava:
Iterable<String> bits = Splitter.on('+').split(s);
String firstPart = Iterables.getFirst(bits, "");
If you're going to use split (either the built-in version or Guava) you don't need to check whether it contains + first - if it doesn't there'll only be one result anyway. Obviously there's a question of efficiency, but it's simpler code:
// Calling split unconditionally
String[] parts = s.split("\\+");
s = parts[0];
Note that writing String[] parts is preferred over String parts[] - it's much more idiomatic Java code.
[+]is simpler
String s = "ddjdjdj+kfkfkf";
if(s.contains ("+"))
{
String parts[] = s.split("[+]");
s = parts[0]; // i want to strip part after +
}
System.out.println(s);

Android - how to replace part of a string by another string?

I have strings with some numbers and english words and I need to translate them to my mother tongue by finding them and replacing them by locallized version of this word. Do you know how to easily achieve replacing words in a string?
Thanks
Edit:
I have tried (part of a string "to" should be replaced by "xyz"):
string.replace("to", "xyz")
But it is not working...
It is working, but it wont modify the caller object, but returning a new String.
So you just need to assign it to a new String variable, or to itself:
string = string.replace("to", "xyz");
or
String newString = string.replace("to", "xyz");
API Docs
public String replace (CharSequence target, CharSequence replacement)
Since: API Level 1
Copies this string replacing
occurrences of the specified target
sequence with another sequence. The
string is processed from the beginning
to the end.
Parameters
target the sequence to replace.
replacement the replacement
sequence.
Returns the resulting string.
Throws NullPointerException if target or replacement is null.
MAY BE INTERESTING TO YOU:
In java, string objects are immutable. Immutable simply means unmodifiable or unchangeable.
Once string object is created its data or state can't be changed but a new string object is created.
In kotlin there is no replaceAll, so I created this loop to replace repeated values ​​in a string or any variable.
var someValue = "https://www.google.com.br/"
while (someValue.contains(".")) {
someValue = someValue.replace(".", "")
}
Log.d("newValue :", someValue)
// in that case the stitches have been removed
//https://wwwgooglecombr/
String str = "to";
str.replace("to", "xyz");
Just try it :)
rekaszeru
I noticed that you commented in 2011 but i thought i should post this answer anyway, in case anyone needs to "replace the original string" and runs into this answer ..
Im using a EditText as an example
// GIVE TARGET TEXT BOX A NAME
EditText textbox = (EditText) findViewById(R.id.your_textboxID);
// STRING TO REPLACE
String oldText = "hello"
String newText = "Hi";
String textBoxText = textbox.getText().toString();
// REPLACE STRINGS WITH RETURNED STRINGS
String returnedString = textBoxText.replace( oldText, newText );
// USE RETURNED STRINGS TO REPLACE NEW STRING INSIDE TEXTBOX
textbox.setText(returnedString);
This is untested, but it's just an example of using the returned string to replace the original layouts string with setText() !
Obviously this example requires that you have a EditText with the ID set to your_textboxID
You're doing only one mistake.
use replaceAll() function over there.
e.g.
String str = "Hi";
String str1 = "hello";
str.replaceAll( str, str1 );

Categories