JAVA replace All except strings starting with ' [duplicate] - java

This question already has answers here:
Java / Replace all Quotation mark
(2 answers)
Closed 3 years ago.
I have a messed up String Like:
String text= "'xhxyxhzx'xcxz" ";
and I want to replaceAll() the other strings with empty except the one starting with '
Something like this:
String cleartext = "";
if (text.contains("'"))
cleartext = text.replaceAll("[text.startingWith("'a-z" + "'0-9")]", "");
out.println(cleartext);
So the output is 'h' 'e' 'll' 'o'
Note: I just found it kinda possible to make it with the replace method but if there are other ways that this can be achieved I don't mind. MASSIVE Thank you!

According to me we can do one thing. I hope you don't mind a no code answer.
Split the string through the character ' and place it into array of string. For example String "h'e'll'o'." becomes h , e , ll , o , .
Disregard all odd number indexes. The string in the even index would be the one inside the ' character. Example in above is "e , o"
Output the string array even indexes or create a new array by step 2.

I think you're looking for something like this.
Pattern pattern = Pattern.compile("'[a-z0-9]+'");
private String function(final String input) {
final Matcher matcher = pattern.matcher(input);
final StringBuilder sb = new StringBuilder();
while (matcher.find()) {
if (sb.length() > 0) {
sb.append(" ");
}
sb.append(matcher.group());
}
return sb.toString();
}
However, I'm not really sure about the rules you want to apply in order to get the expected result. Ex: "'''" => "'" ?

Related

Perform replace on a string but ignore some pattern [duplicate]

This question already has answers here:
Regex: match only outside parenthesis (so that the text isn't split within parenthesis)?
(2 answers)
Closed 3 years ago.
I (Regex noob) am trying to perform replace operation on a string containing some pattern. For example
AAA-BBB-CCC-{AAA-BBB-AAA-BBB}-CCC-BBB-AAA
In the above I am trying to replace all As with Is but ignore the As inside curly braces.
For this what I could do is to split the entire string on the pattern and perform replace then concatenate the strings.
I was wondering if there is a shorter way in regex so that I could perform something like
String str = "AAA-BBB-CCC-{AAA-BBB-AAA-BBB}-CCC-BBB-AAA";
str = str.replaceButIgnorePattern("A", "I","\\{(.*?)\\}");
System.out.print(str); //III-BBB-CCC-{AAA-BBB-AAA-BBB}-CCC-BBB-III
And the pattern can be like
contains any character
can be at starting, in between or at the end of the string
Considering there are no nested braces, a solution is to match a substring inside the closest { and } and match and capture the pattern to replace, and then check if the Group 1 is not null and then act accordingly.
In Java 9+, you may use
String text = "AAA-BBB-CCC-{AAA-BBB-AAA-BBB}-CCC-BBB-AAA";
Pattern r = Pattern.compile("\\{[^{}]*}|(A)");
Macher m = r.matcher(text);
String result = m.replaceAll(x -> x.group(1) != null ? "I" : x.group() );
System.out.println( result );
See the online demo.
Here, \{[^{}]*} matches {, any 0+ chars other than { and }, and then }, or (|) captures A into Group 1.
Equivalent code for older Java versions:
String text = "AAA-BBB-CCC-{AAA-BBB-AAA-BBB}-CCC-BBB-AAA";
Pattern r = Pattern.compile("\\{[^{}]*}|(A)");
Matcher m = r.matcher(text);
StringBuffer sb = new StringBuffer();
while (m.find()) {
if (m.group(1) == null) {
m.appendReplacement(sb, m.group(0));
} else {
m.appendReplacement(sb, "I");
}
}
m.appendTail(sb);
System.out.println(sb);
See the online Java demo.
You may also use a common workaround for any Java version:
str = str.replaceAll("A(?![^{}]*})", "I");
where (?![^{}]*}) makes sure there is no any 0+ occurrences of { and } followed with a } immediately to the right of the current location. NOTE this approach implies that the string contains a balanced amount of open/close braces.

Replace digits in String with that amount of a certain character using regex one-liner

Is it possible to replace digits in a String with that amount of a certain character like 'X' using a regex? (I.e. replace "test3something8" with "testXXXsomethingXXXXXXXX")?
I know I could use a for-loop, but I'm looking for an as short-as-possible (regex) one-liner solution (regarding a code-golf challenge - and yes, I am aware of the codegolf-SE, but this is a general Java question instead of a codegolf question).
I know how to replace digits with one character:
String str = "test3something8".replaceAll("[1-9]", "X"); -> str = "testXsomethingX"
I know how to use groups, in case you want to use the match, or add something after every match instead of replacing it:
String str = "test3something8".replaceAll("([1-9])", "$1X"); -> str = "test3Xsomething8X"
I know how to create n amount of a certain character:
int n = 5; String str = new String(new char[n]).replace('\0', 'X'); -> str = "XXXXX"
Or like this:
int n = 5; String str = String.format("%1$"+n+"s", "").replace(' ', 'X'); -> str = "XXXXX";
What I want is something like this (the code below obviously doesn't work, but it should give an idea of what I somehow want to achieve - preferably even a lot shorter):
String str = "test3Xsomething8X"
.replaceAll("([1-9])", new String(new char[new Integer("$1")]).replace('\0', 'X')));
// Result I want it to have: str = "testXXXsomethingXXXXXXXX"
As I said, this above doesn't work because "$1" should be used directly, so now it's giving a
java.lang.NumberFormatException: For input string: "$1"
TL;DR: Does anyone know a one-liner to replace a digit in a String with that amount of a certain character?
If you really want to have it as a one-liner. A possible solution (see it more as a PoC) could be to use the Stream API.
String input = "test3something8";
input.chars()
.mapToObj(
i -> i >= '0' && i <= '9' ?
new String(new char[i-'0']).replace('\0', 'X')
: "" + ((char)i)
)
.forEach(System.out::print);
output
testXXXsomethingXXXXXXXX
note No investigation has been done for performance, scalability, to be GC friendly, etc.

Split a string based on pattern and merge it back

I need to split a string based on a pattern and again i need to merge it back on a portion of string.
for ex: Below is the actual and expected strings.
String actualstr="abc.def.ghi.jkl.mno";
String expectedstr="abc.mno";
When i use below, i can store in a Array and iterate over to get it back. Is there anyway it can be done simple and efficient than below.
String[] splited = actualstr.split("[\\.\\.\\.\\.\\.\\s]+");
Though i can acess the string based on index, is there any other way to do this easily. Please advise.
You do not understand how regexes work.
Here is your regex without the escapes: [\.\.\.\.\.\s]+
You have a character class ([]). Which means there is no reason to have more than one . in it. You also don't need to escape .s in a char class.
Here is an equivalent regex to your regex: [.\s]+. As a Java String that's: "[.\\s]+".
You can do .split("regex") on your string to get an array. It's very simple to get a solution from that point.
I would use a replaceAll in this case
String actualstr="abc.def.ghi.jkl.mno";
String str = actualstr.replaceAll("\\..*\\.", ".");
This will replace everything with the first and last . with a .
You could also use split
String[] parts = actualString.split("\\.");
string str = parts[0]+"."+parts[parts.length-1]; // first and last word
public static String merge(String string, String delimiter, int... partnumbers)
{
String[] parts = string.split(delimiter);
String result = "";
for ( int x = 0 ; x < partnumbers.length ; x ++ )
{
result += result.length() > 0 ? delimiter.replaceAll("\\\\","") : "";
result += parts[partnumbers[x]];
}
return result;
}
and then use it like:
merge("abc.def.ghi.jkl.mno", "\\.", 0, 4);
I would do it this way
Pattern pattern = Pattern.compile("(\\w*\\.).*\\.(\\w*)");
Matcher matcher = pattern.matcher("abc.def.ghi.jkl.mno");
if (matcher.matches()) {
System.out.println(matcher.group(1) + matcher.group(2));
}
If you can cache the result of
Pattern.compile("(\\w*\\.).*\\.(\\w*)")
and reuse "pattern" all over again this code will be very efficient as pattern compilation is the most expensive. java.lang.String.split() method that other answers suggest uses same Pattern.compile() internally if the pattern length is greater then 1. Meaning that it will do this expensive operation of Pattern compilation on each invocation of the method. See java.util.regex - importance of Pattern.compile()?. So it is much better to have the Pattern compiled and cached and reused.
matcher.group(1) refers to the first group of () which is "(\w*\.)"
matcher.group(2) refers to the second one which is "(\w*)"
even though we don't use it here but just to note that group(0) is the match for the whole regex.

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 do I break a string into arguments, respecting quotes? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Regex for splitting a string using space when not surrounded by single or double quotes
How can I break a string like this:
String args = "\"file one.txt\" filetwo.txt some other \"things here\"";
into its arguments / parameters while respecting quotes?
So in the above example, the arguments would be broken into:
args[0] = file one.txt
args[1] = filetwo.txt
args[2] = some
args[3] = other
args[4] = things here
I understand how to use split(" "), but I want to combine terms that are in quotes.
Assuming that you don't have to use regex and your input doesn't contains nested quotes you can achieve this in one iteration over your String characters:
String data = "\"file one.txt\" filetwo.txt some other \"things here\"";
List<String> tokens = new ArrayList<String>();
StringBuilder sb = new StringBuilder();
boolean insideQuote = false;
for (char c : data.toCharArray()) {
if (c == '"')
insideQuote = !insideQuote;
if (c == ' ' && !insideQuote) {//when space is not inside quote split..
tokens.add(sb.toString()); //token is ready, lets add it to list
sb.delete(0, sb.length()); //and reset StringBuilder`s content
} else
sb.append(c);//else add character to token
}
//lets not forget about last token that doesn't have space after it
tokens.add(sb.toString());
String[] array=tokens.toArray(new String[0]);
System.out.println(Arrays.toString(array));
Output:
["file one.txt", filetwo.txt, some, other, "things here"]
If you haven't problems introducing a dependency you can use Commons cli from Apache.
It will simplify command line parsing and make it more usable for users.

Categories