Conditionally replacing the last characters of a string - java

I have a string, say xyzabc_1_1.
I want to first test if the last characters are _1 and if so, replace the last _1 with _01_1. The string will become xyzabc_1_01_1.
For finding if the last digits are _1 I'm using
str1.matches("^.*_\\d$")
But don't know the second part, i.e. how to replace the last occurrence with _01_1.

To replace the string, you can just grab a substring and concatenate your new suffix. Additionally, you can use endsWith instead of the regular expression. IMHO it's more readable.
public String replaceSuffix (String target) {
if (!target.endsWith("_1")) {
return target;
}
return target.substring(0, target.length() - 2) + "_01_1";
}
And just for the fun of it, here's a more reusable version for replacing different things:
public String replaceSuffix (String target, String suffix, String replacement) {
if (!target.endsWith(suffix)) {
return target;
}
String prefix = target.substring(0, target.length() - suffix.length());
return prefix + replacement;
}
Invoked as (for your specific example):
String replaced = replaceSuffix("xyzabc_1_1", "_1", "_01_1");
Depending on your expected input, you might also want some null/empty/length checks on str.

This is a simple one-liner, using replaceAll() and back-references:
String str2 = str1.replaceAll("_\\d$", "_01$0");
It's not clear if the 01 is based on the 1 or is a constant. ie if 2 were to become 02_2 then do this instead: str1.replaceAll("_(\\d)$", "_0$1_$1")
Here's a test:
String str1 = "xyzabc_1_1";
String str2 = str1.replaceAll("_\\d$", "_01$0");
System.out.println(str2);
Output:
xyzabc_1_01_1

You'd rather replace the whole string with the new one. Create a new string with the '_01_1' concatenated. Then replace.

Done but needs optimization...
String str1 = "xyzabc_1";
/* System.out.println(str1.matches("^.*_\\d$")); */
try {
if (str1.matches("^.*_\\d$")) {
String cutted = str1.substring(str1.lastIndexOf("_"),
str1.length());
str1 = str1.replaceAll(cutted, "_01" + cutted); //
System.out.println(str1);
} else {
}
} catch (Exception e) {
e.printStackTrace();
}

Related

How to remove single and double quotes at both ends of a string

I would like to remove single or double quotes from both ends of a string. The string may contain additional quotes or/and double quotes which shall remain untouched - so removeAll() is not an option.
String one = "\"some string\"";
String two = "'some \"other string\"'";
// expected result
// some string
// some "other string"
What I tried so far:
two = two.replace("/^[\"\'])|([\"\']$/g", "");
The following would work but there must be a much more elegant way to achieve this..
if ((one != null && one.length() > 1) && ((one.startsWith("\"") && one.endsWith("\"")) ||
(one.startsWith("\'") && one.endsWith("\'")))) {
one = one.substring(1, one.length() - 1);
}
Any ideas?
Update / clarification
My use case is the command line interface of an app, where the user can also drag files/paths into, instead of typing them.
Under Windows the dragged files are beeing surrounded by double quotes, under Linux with single quotes. All I want to do is get rid of them. So in my use case the quotes are always symetric (they match).
But I can perfectly live with a solution, which would strip them even if they wouldn't match, because they always do
Option 1: Removing all single and double quotes from start and end
You can use replaceAll which accepts a regular expression - replace doesn't - and do it twice, once for quotes at the start of the string and once for quotes at the end:
public class Test {
public static void main(String[] args) {
String text = "\"'some \"other string\"'";
String trimmed = text
.replaceAll("^['\"]*", "")
.replaceAll("['\"]*$", "");
System.out.println(trimmed);
}
}
The ^ in the first replacement anchors the quotes to the start of the string; the $ in the second anchors the quotes to the end of the string.
Note that this doesn't try to "match" quotes at all, unlike your later code.
Option 2: Removing a single quote character from start and end, if they match
String trimmed = text.replaceAll("^(['\"])(.*)\\1$", "$2");
This will trim exactly one character from the start and end, if they both match. Sample:
public class Test {
public static void main(String[] args) {
trim("\"foo\"");
trim("'foo'");
trim("\"bar'");
trim("'bar\"");
trim("\"'baz'\"");
}
static void trim(String text) {
String trimmed = text.replaceAll("^(['\"])(.*)\\1$", "$2");
System.out.println(text + " => " + trimmed);
}
}
Output:
"foo" => foo
'foo' => foo
"bar' => "bar'
'bar" => 'bar"
"'baz'" => 'baz'
To complete Jon Skeet response, if you want to remove quotes only if there is one on the beginning AND one on the end you can do :
public String removeQuotes(String str) {
Pattern pattern = Pattern.compile("^['\"](.*)['\"]$");
Matcher matcher = pattern.matcher(str);
if (matcher.find()) {
return matcher.group(1);
} else {
return str;
}
}
if you are looking in javascript try this :
function t(k){
var l="\"\'"; //you can add more chars here.
if (l.indexOf(k[0])>-1) {
return t(k.substr(1,k.length));
} else if (l.indexOf(k[k.length-1])>-1) {
return t(k.substr(0,k.length-1));
} else {
return k;
}
}
One possible way with using replaceFirst():
String one = "\"some string\"";
System.out.println("one: " + one);
one = one.replaceFirst("\"", "");
String reversed = new StringBuilder(one).reverse().toString();
one = one.replaceFirst("\"", "");
one = new StringBuilder(reversed).reverse().toString();
System.out.println("result: " + one);

How to split a String based on conditions

Hi I need to split a String in java based on conditions
the String might be in two formats
1. IF the format is like this WG/A/0-5 then I need to check if the last part starts with "0-" then I need the middle part to be extracted (ie:"A")
2.The Second format is WG/A/3-3 here it is 3-3 ie:other than 0) here I need to extract (A/3) .
I have tried like this
String parent = StringPool.BLANK;
if(wgCode.split(StringPool.FORWARD_SLASH)[2].startsWith("0-")) {
parent = wgCode.split(StringPool.FORWARD_SLASH)[1];
} else if(!wgCode.split(StringPool.FORWARD_SLASH)[2].startsWith("0-")) {
parent = wgCode.split(StringPool.FORWARD_SLASH)[1]+"/"+wgCode.split(StringPool.FORWARD_SLASH)[2].split("-")[0];
}
_log.info("parent parent"+parent);
Use Regular Expressions and String.contains to check your conditions and String.indexOf and String.substring to split your String.
The following method will work for your example:
public String getString(String input)
{
if(input.matches(".*/.*/0.*"))
{
String yourString = input.substring(input.indexOf("/")+1);
yourString = yourString.substring(0, yourString.indexOf("/"));
return yourString;
}
else
{
String yourString = input.substring(input.indexOf("/")+1);
yourString = yourString.substring(0, yourString.indexOf("/")+2);
return yourString;
}
}
With the regular expression .*/.*/0.* you find all Strings that start with a 0 after the second /.
use String#contains(String) to check whether 0- is there nor not.
String str="WG/A/0-5";
String str1="WG/A/3-3";
if(str.contains("0-"))
System.out.println(str.substring(str.indexOf("/")+1,str.indexOf("/",str.indexOf("/") + 1)));//A
if(!str1.contains("0-"))
System.out.println(str1.substring(str1.indexOf("/")+1,str1.indexOf("-")));//A/3
Maybe something like this:
String input = "WG/A/0-5";
String[] parts = input.split("/");
if( parts[2].charAt(0) == '0' ){
......
String charAt, substring should solve your problem:
String myValue = input.charAt(5) == '0' ? input.substring(3, 4) : input
.substring(3, 6);

Java String index out of range error

I'm running into some issues with some java code that I do not know how to fix. I was wondering if I could get some help with figuring out why I keep getting
java.lang.StringIndexOutOfBoundsException: String index out of range: 1
Here's the code snippet where the problem is popping up (its part of a larger package for an assignment..) :
public class MyMapper extends Mapper {
#Override
//method takes docName and data as string
public void map(String documentID, String document) {
//this string array hold all the delimiters for our split
//String[] separators = {",", ".", "!", "?", ";", ":", "-", "' "," "};
//splits the string 'document' according to delimiters
String[] words = document.split(",|\\.|\\!|\\?|\\;|\\:|\\-|\\' |\\ |\\'.");
// for each word in String[] words, check that each word is legitimate
for (String word : words) {
if (isAlpha(word)){
//System.out.println(word);
emit(word.substring(0, 1).toUpperCase() , "1");
}
else;
}
}
// private helper method to check that each word is legitimate (alphas-only)
private boolean isAlpha(String name) {
char[] chars = name.toCharArray();
for (char c : chars) {
if(!Character.isLetter(c)) {
return false;
}
}
return true;
}
}
What I am trying to do is take in a document (stored in string form through bufferedReader) and seize the first letter of each word in the doc, and capitalize them.
***** Updated Code*****
I decided to go with the suggested check for the empty "word" in my private helper method. Everything works now.
Here is the updated code for documentation purposes:
// private helper method to check that each word is legitimate (alphas-only)
private boolean isAlpha(String name) {
if (name.equals(""))
return false;
char[] chars = name.toCharArray();
for (char c : chars) {
if(!Character.isLetter(c)) {
return false;
}
}
return true;
Looks like sometimes your word is empty. Make a check first to see that you've got something to work with:
if (isAlpha(word)){
if(!word.isEmpty()){ //you could also use 'if(word.length == 0)'
emit(word.substring(0, 1).toUpperCase() , "1");
}
}
Alternatively, make that check in your isAlpha() method.
If your word is empty just return a false from your isAlpha() like this
private boolean isAlpha(String name) {
if (name.equals(""))
return false;
char[] chars = name.toCharArray();
for (char c : chars) {
if(!Character.isLetter(c)) {
return false;
}
}
return true;
}
}
For some strings, your split regex can produce empty strings, for example in the not-at-all unusual case that a comma is followed by a space, e.g., the string document = "Some words, with comma."; will be split into [Some, words, , with, comma].
Instead of enumerating all the non-word characters that you can think of, I suggest using the \W character class (non-alphanumeric character) and also allowing multiple of those, i.e. words = document.split("\\W+");. This gives you [Some, words, with, comma].
If you need more control about the characters to split by and don't want to use a character class, you can still put the characters into [...]+ to shorten the regex and to split by groups of those, too, using words = document.split("[|.!?,;:' -]+"). (Inside [...], you do not need to escape all of those, as long as the - is last, so it's unambiguous.)
Would something like this do?
String text = "es saß ein wiesel, auf einem kiesel.";
String[] parts = text.split("\\s+");
StringBuilder resultingString = new StringBuilder();
for (String part : parts) {
part = Character.toUpperCase(part.charAt(0))
+ part.substring(1, part.length());
resultingString.append(part + " ");
}
text = resultingString.toString().substring(0,
resultingString.length() - 1);
System.out.println(text);

Remove trailing substring from String in Java

I am looking to remove parts of a string if it ends in a certain string.
An example would be to take this string: "am.sunrise.ios#2x.png"
And remove the #2x.png so it looks like: "am.sunrise.ios"
How would I go about checking to see if the end of a string contains "#2x.png" and remove it?
You could check the lastIndexOf, and if it exists in the string, use substring to remove it:
String str = "am.sunrise.ios#2x.png";
String search = "#2x.png";
int index = str.lastIndexOf(search);
if (index > 0) {
str = str.substring(0, index);
}
Assuming you have a string initialized as String file = "am.sunrise.ios#2x.png";.
if(file.endsWith("#2x.png"))
file = file.substring(0, file.lastIndexOf("#2x.png"));
The endsWith(String) method returns a boolean determining if the string has a certain suffix. Depending on that you can replace the string with a substring of itself starting with the first character and ending before the index of the character that you are trying to remove.
private static String removeSuffixIfExists(String key, String suffix) {
return key.endswith(suffix)
? key.substring(0, key.length() - suffix.length())
: key;
}
}
String suffix = "#2x.png";
String key = "am.sunrise.ios#2x.png";
String output = removeSuffixIfExists(key, suffix);
public static void main(String [] args){
String word = "am.sunrise.ios#2x.png";
word = word.replace("#2x.png", "");
System.out.println(word);
}
If you want to generally remove entire content of string from # till end you can use
yourString = yourString.replaceAll("#.*","");
where #.* is regex (regular expression) representing substring starting with # and having any character after it (represented by .) zero or more times (represented by *).
In case there will be no #xxx part your string will be unchanged.
If you want to change only this particular substring #2x.png (and not substirng like #3x.png) while making sure that it is placed at end of your string you can use
yourString = yourString.replaceAll("#2x\\.png$","");
where
$ represents end of string
\\. represents . literal (we need to escape it since like shown earlier . is metacharacter representing any character)
Since I was trying to do this on an ArrayList of items similarly styled I ended up using the following code:
for (int image = 0; image < IBImages.size(); image++) {
IBImages.set(image, IBImages.get(image).split("~")[0].split("#")[0].split(".png")[0]);
}
If I have a list of images with the names
[am.sunrise.ios.png, am.sunrise.ios#2x.png, am.sunrise.ios#3x.png, am.sunrise.ios~ipad.png, am.sunrise.ios~ipad#2x.png]
This allows me to split the string into 2 parts.
For example, "am.sunrise.ios~ipad.png" will be split into "am.sunrise.ios" and "~ipad.png" if I split on "~". I can just get the first part back by referencing [0]. Therefore I get what I'm looking for in one line of code.
Note that image is "am.sunrise.ios~ipad.png"
You could use String.split():
public static void main(String [] args){
String word = "am.sunrise.ios#2x.png";
String[] parts = word.split("#");
if (parts.length == 2) {
System.out.println("looks like user#host...");
System.out.println("User: " + parts[0]);
System.out.println("Host: " + parts[1]);
}
}
Then you haven an array of Strings, where the first element contains the part before "#" and the second element the part after the "#".
Combining the answers 1 and 2:
String str = "am.sunrise.ios#2x.png";
String search = "#2x.png";
if (str.endsWith(search)) {
str = str.substring(0, str.lastIndexOf(search));
}

Detect and return characters in a Java string

I'm trying to write a method that will scan a string for certain characters, and report back which of them (if any) were found:
// Special characters are ~, #, #, and *
// If text == "Hello~Clarice, you're s#o ambitious", then this
// method should return a string == "~#". If no special characters
// found, return null. If the same special character occurs 2+ times,
// ignore it and do not return strings with duplicate special chars, like
// "###***", etc. --> just "##*".
public String detectAndGetSpecialCharacters(String text) {
Pattern p = Pattern.compile("[~##*]");
Matcher m = pattern.matcher(text);
String specialCharactersFound = null;
if(m.find()) {
// ???
}
return specialCharactersFound;
}
I've completed the detect portion of this method, but am struggling to find an efficient/elegant way of using the Matcher to tell me which special characters were found, and furthermore, to concatenate them all together (removing duplicates!) and return them. Thanks in advance!
Why not simply using String.indexOf(specialChar). Call this method ones for each special char if the result is >= 0 it means that that the special char is present at least one time.
Then order the special chars according the index found to build the resluting String.
Not very elegant, but I think it's efficient because:
you don't have to remove duplicates.
if you have many (duplicate) special chars it won't have any impact
Edit (here is sample code)
private static class SpecialChar implements Comparable<SpecialChar>{
Integer position;
char c;
private SpecialChar(char c, Integer position) {
this.c = c;
this.position = position;
}
#Override
public int compareTo(SpecialChar another) {
return position.compareTo(another.position);
}
}
public static void main(String[] args){
String input = args[0];
char[] specialsChars = new char[]{'*','#','~','#'};
List<SpecialChar> results = new ArrayList<SpecialChar>();
for(char c:specialsChars){
int position = input.indexOf(c);
if(position>-1)results.add(new SpecialChar(c,position));
}
Collections.sort(results);
StringBuilder builder = new StringBuilder();
for(SpecialChar sp:results){
builder.append(sp.c);
}
System.out.print(builder.toString());
}
Rather than using a String, you can use a StringBuilder, and append each matched character to it, if it is not already there: -
StringBuilder builder = new StringBuilder();
while (m.find()) {
String str = m.group();
if (!builder.toString().contains(str)) {
builder.append(str);
}
}
// And finally
return builder.toString();
Another way would be to maintain a Set<String>, and keep on adding matched characters to it. It will automatically remove duplicates. And then you can merge the values of the Set to form a String using Apache Commons StringUtils#join() method. Or you can simply iterate over the Set and append each string to a StringBuilder object. Whatever way you like would fit.
You need capturing-group. Just enclose your regex with parentheses and for each matcher#find get it. It will be something like:
public String detectAndGetSpecialCharacters(String text) {
Pattern p = Pattern.compile("([~##*])");
Matcher m = pattern.matcher(text);
Set<String> specialCharacters = new HashSet<String>();
if (m.find()) {
specialCharacters.add(m.group(1));
}
StringBuilder specialCharactersFound = new StringBuilder();
for (String specialChar : specialCharacters) {
specialCharactersFound.append(specialChar);
}
return specialCharactersFound.toString();
}
Adding to Set will remove the duplicates and you build your String with special characters at the end. And it will not return null, that normally is not a good thing.
EDIT
You don't actually need the capturing-group, as your regex is getting only the special characters. You could just use Matcher#group. But, it's a good thing to learn one more thing ;)

Categories

Resources