JAVA: Replacing words in string - java

I want to replace words in a string, but I am having little difficulties. Here is what I want to do. I have string:
String a = "I want to replace some words in this string";
It should work like some kind of a translator. I am doing this with String.replaceAll(), but it doesn't work completely because of this. Let's say I am translating from English to German, than this should be the output (Ich means I in German).
String toTranslate = "I";
String translated = "Ich";
a = a.replaceAll(toTranslate.toLowerCase(), translated.toLowerCase());
Now the output of the String a will be this:
"ich want to replace some words ich**n** **th**ich**s** **str**ich**ng**"
How to replace just the words, not the subwords in the words?

replaceAll uses regex, so you may add word boundaries or look-around mechanisms to check if there are no non-space characters surrounding word you want to replace.
String toTranslate = "I";
String translated = "Ich";
a = a.replaceAll("(?<!\\S)"+toTranslate.toLowerCase()+"(?!\\S)", translated.toLowerCase());
You can also add quotation mechanism to escape any regex metacharacters like + * ( inside word you want to replace. BTW you don't need to change your string to lower case, simply add case-insensitive flag to regex (?i).
a = a.replaceAll("(?i)(?<!\\S)"+Pattern.quote(toTranslate)+"(?!\\S)", translated.toLowerCase());

Use split(" ") for getting each word in the sentence. And then use replaceAll on each word.
String a = "I want to replace some words in this string";
String toTranslate = "I";
String translated = "Ich";
String newString[]=a.split(" ");
for (String string : newString) {
string=string.replaceAll(toTranslate, toTranslate.toLowerCase());//Adding this line ensures you dont miss any uppercase toTranslate
string=string.replaceAll(toTranslate.toLowerCase(), translated.toLowerCase());
System.out.println("after translation ="+string);
}

String toTranslate = "I ";
String translated = "Ich ";
a = a.replaceAll(toTranslate.toLowerCase(), translated.toLowerCase());
If you add a space after the "I" it should replace it when it comes to the word "Ich" but if your word ends in a "I" then thats another problem

If you assume that I will always be capitalized in English as it should be then
a = a.replaceAll(toTranslate, translated);
will work, otherwise you need to replace both cases
a = a.replaceAll(toTranslate, translated);
a = a.replaceAll("([^a-zA-Z])("+toTranslate.toLowerCase()+")([^a-zA-Z])", "$1"+translated.toLowerCase()+"$3");
Here is a working example

Yes, the word boundaries are the solution. I just did this in the regex:
text.replaceAll("\\b" + parts1[i] + "\\b", map.element.value);
Don't be confused with the second argument it's string (from Hash table).

You can use RegEx's word bound, which is \b
String toTranslate = "\\bI\\b";
String translated = "Ich";
a = a.replaceAll(toTranslate.toLowerCase(), translated.toLowerCase());
This should ensure I is separated entirely into its own word
Edit: I misread the question and realized you want whole words. See above, as I have accounted for that

Related

Regex Java when we have specific text upto a pattern

As i haven't much worked on regex, can someone help me out in getting the answer for below thing:
(1)I want to remove a text say Element
(2)It may of may not followed by delimiter say pipe(||)
I tried below thing, but it is not working in the way i want:
String str = "String:abc||Element:abc||Value:abc"; // Sample text 1
String str1 = "String:abc||Element:abc"; // Sample text 2
System.out.println(str.replaceFirst("Element.*\\||", ""));
System.out.println(str1.replaceFirst("Element.*\\||", ""));
Required output in above cases:
String:abc||Value:abc //for the first case
String:abc //for the second case
Assuming that you can decide to give another value to the original pattern which is Element in this case, you can use Pattern.quote to escape it as below:
String str = "String:abc||Element:abc||Value:abc"; // Sample text 1
String str1 = "String:abc||Element:abc"; // Sample text 2
String originalPattern = "Element";
String pattern = String.format("\\|{2}%s[^\\|]+", Pattern.quote(originalPattern));
System.out.println(str.replaceFirst(pattern, ""));
System.out.println(str1.replaceFirst(pattern, ""));
Your patter is then generic and its value is String.format("\\|{2}%s[^\\|]+", Pattern.quote(originalPattern))
Output:
String:abc||Value:abc
String:abc
You put the escape wrong. It should be:
Element(.*?\|\||.*$)
Put the escape on each pipe, and use ? for non greedy Regex so you only replace just enough string, not everything.
String text = "String:abc||Element:abc||Value:abc";
text = text.replaceAll("\\belement\\b", "");
you might need to use replace all this will replace all element from your string here i am using '\b' word boundary in java regular expression in between the words

String split regex [duplicate]

I'm new to regular expressions and would appreciate your help. I'm trying to put together an expression that will split the example string using all spaces that are not surrounded by single or double quotes. My last attempt looks like this: (?!") and isn't quite working. It's splitting on the space before the quote.
Example input:
This is a string that "will be" highlighted when your 'regular expression' matches something.
Desired output:
This
is
a
string
that
will be
highlighted
when
your
regular expression
matches
something.
Note that "will be" and 'regular expression' retain the space between the words.
I don't understand why all the others are proposing such complex regular expressions or such long code. Essentially, you want to grab two kinds of things from your string: sequences of characters that aren't spaces or quotes, and sequences of characters that begin and end with a quote, with no quotes in between, for two kinds of quotes. You can easily match those things with this regular expression:
[^\s"']+|"([^"]*)"|'([^']*)'
I added the capturing groups because you don't want the quotes in the list.
This Java code builds the list, adding the capturing group if it matched to exclude the quotes, and adding the overall regex match if the capturing group didn't match (an unquoted word was matched).
List<String> matchList = new ArrayList<String>();
Pattern regex = Pattern.compile("[^\\s\"']+|\"([^\"]*)\"|'([^']*)'");
Matcher regexMatcher = regex.matcher(subjectString);
while (regexMatcher.find()) {
if (regexMatcher.group(1) != null) {
// Add double-quoted string without the quotes
matchList.add(regexMatcher.group(1));
} else if (regexMatcher.group(2) != null) {
// Add single-quoted string without the quotes
matchList.add(regexMatcher.group(2));
} else {
// Add unquoted word
matchList.add(regexMatcher.group());
}
}
If you don't mind having the quotes in the returned list, you can use much simpler code:
List<String> matchList = new ArrayList<String>();
Pattern regex = Pattern.compile("[^\\s\"']+|\"[^\"]*\"|'[^']*'");
Matcher regexMatcher = regex.matcher(subjectString);
while (regexMatcher.find()) {
matchList.add(regexMatcher.group());
}
There are several questions on StackOverflow that cover this same question in various contexts using regular expressions. For instance:
parsings strings: extracting words and phrases
Best way to parse Space Separated Text
UPDATE: Sample regex to handle single and double quoted strings. Ref: How can I split on a string except when inside quotes?
m/('.*?'|".*?"|\S+)/g
Tested this with a quick Perl snippet and the output was as reproduced below. Also works for empty strings or whitespace-only strings if they are between quotes (not sure if that's desired or not).
This
is
a
string
that
"will be"
highlighted
when
your
'regular expression'
matches
something.
Note that this does include the quote characters themselves in the matched values, though you can remove that with a string replace, or modify the regex to not include them. I'll leave that as an exercise for the reader or another poster for now, as 2am is way too late to be messing with regular expressions anymore ;)
If you want to allow escaped quotes inside the string, you can use something like this:
(?:(['"])(.*?)(?<!\\)(?>\\\\)*\1|([^\s]+))
Quoted strings will be group 2, single unquoted words will be group 3.
You can try it on various strings here: http://www.fileformat.info/tool/regex.htm or http://gskinner.com/RegExr/
The regex from Jan Goyvaerts is the best solution I found so far, but creates also empty (null) matches, which he excludes in his program. These empty matches also appear from regex testers (e.g. rubular.com).
If you turn the searches arround (first look for the quoted parts and than the space separed words) then you might do it in once with:
("[^"]*"|'[^']*'|[\S]+)+
(?<!\G".{0,99999})\s|(?<=\G".{0,99999}")\s
This will match the spaces not surrounded by double quotes.
I have to use min,max {0,99999} because Java doesn't support * and + in lookbehind.
It'll probably be easier to search the string, grabbing each part, vs. split it.
Reason being, you can have it split at the spaces before and after "will be". But, I can't think of any way to specify ignoring the space between inside a split.
(not actual Java)
string = "This is a string that \"will be\" highlighted when your 'regular expression' matches something.";
regex = "\"(\\\"|(?!\\\").)+\"|[^ ]+"; // search for a quoted or non-spaced group
final = new Array();
while (string.length > 0) {
string = string.trim();
if (Regex(regex).test(string)) {
final.push(Regex(regex).match(string)[0]);
string = string.replace(regex, ""); // progress to next "word"
}
}
Also, capturing single quotes could lead to issues:
"Foo's Bar 'n Grill"
//=>
"Foo"
"s Bar "
"n"
"Grill"
String.split() is not helpful here because there is no way to distinguish between spaces within quotes (don't split) and those outside (split). Matcher.lookingAt() is probably what you need:
String str = "This is a string that \"will be\" highlighted when your 'regular expression' matches something.";
str = str + " "; // add trailing space
int len = str.length();
Matcher m = Pattern.compile("((\"[^\"]+?\")|('[^']+?')|([^\\s]+?))\\s++").matcher(str);
for (int i = 0; i < len; i++)
{
m.region(i, len);
if (m.lookingAt())
{
String s = m.group(1);
if ((s.startsWith("\"") && s.endsWith("\"")) ||
(s.startsWith("'") && s.endsWith("'")))
{
s = s.substring(1, s.length() - 1);
}
System.out.println(i + ": \"" + s + "\"");
i += (m.group(0).length() - 1);
}
}
which produces the following output:
0: "This"
5: "is"
8: "a"
10: "string"
17: "that"
22: "will be"
32: "highlighted"
44: "when"
49: "your"
54: "regular expression"
75: "matches"
83: "something."
I liked Marcus's approach, however, I modified it so that I could allow text near the quotes, and support both " and ' quote characters. For example, I needed a="some value" to not split it into [a=, "some value"].
(?<!\\G\\S{0,99999}[\"'].{0,99999})\\s|(?<=\\G\\S{0,99999}\".{0,99999}\"\\S{0,99999})\\s|(?<=\\G\\S{0,99999}'.{0,99999}'\\S{0,99999})\\s"
Jan's approach is great but here's another one for the record.
If you actually wanted to split as mentioned in the title, keeping the quotes in "will be" and 'regular expression', then you could use this method which is straight out of Match (or replace) a pattern except in situations s1, s2, s3 etc
The regex:
'[^']*'|\"[^\"]*\"|( )
The two left alternations match complete 'quoted strings' and "double-quoted strings". We will ignore these matches. The right side matches and captures spaces to Group 1, and we know they are the right spaces because they were not matched by the expressions on the left. We replace those with SplitHere then split on SplitHere. Again, this is for a true split case where you want "will be", not will be.
Here is a full working implementation (see the results on the online demo).
import java.util.*;
import java.io.*;
import java.util.regex.*;
import java.util.List;
class Program {
public static void main (String[] args) throws java.lang.Exception {
String subject = "This is a string that \"will be\" highlighted when your 'regular expression' matches something.";
Pattern regex = Pattern.compile("\'[^']*'|\"[^\"]*\"|( )");
Matcher m = regex.matcher(subject);
StringBuffer b= new StringBuffer();
while (m.find()) {
if(m.group(1) != null) m.appendReplacement(b, "SplitHere");
else m.appendReplacement(b, m.group(0));
}
m.appendTail(b);
String replaced = b.toString();
String[] splits = replaced.split("SplitHere");
for (String split : splits) System.out.println(split);
} // end main
} // end Program
If you are using c#, you can use
string input= "This is a string that \"will be\" highlighted when your 'regular expression' matches <something random>";
List<string> list1 =
Regex.Matches(input, #"(?<match>\w+)|\""(?<match>[\w\s]*)""|'(?<match>[\w\s]*)'|<(?<match>[\w\s]*)>").Cast<Match>().Select(m => m.Groups["match"].Value).ToList();
foreach(var v in list1)
Console.WriteLine(v);
I have specifically added "|<(?[\w\s]*)>" to highlight that you can specify any char to group phrases. (In this case I am using < > to group.
Output is :
This
is
a
string
that
will be
highlighted
when
your
regular expression
matches
something random
1st one-liner using String.split()
String s = "This is a string that \"will be\" highlighted when your 'regular expression' matches something.";
String[] split = s.split( "(?<!(\"|').{0,255}) | (?!.*\\1.*)" );
[This, is, a, string, that, "will be", highlighted, when, your, 'regular expression', matches, something.]
don't split at the blank, if the blank is surrounded by single or double quotes
split at the blank when the 255 characters to the left and all characters to the right of the blank are neither single nor double quotes
adapted from original post (handles only double quotes)
I'm reasonably certain this is not possible using regular expressions alone. Checking whether something is contained inside some other tag is a parsing operation. This seems like the same problem as trying to parse XML with a regex -- it can't be done correctly. You may be able to get your desired outcome by repeatedly applying a non-greedy, non-global regex that matches the quoted strings, then once you can't find anything else, split it at the spaces... that has a number of problems, including keeping track of the original order of all the substrings. Your best bet is to just write a really simple function that iterates over the string and pulls out the tokens you want.
A couple hopefully helpful tweaks on Jan's accepted answer:
(['"])((?:\\\1|.)+?)\1|([^\s"']+)
Allows escaped quotes within quoted strings
Avoids repeating the pattern for the single and double quote; this also simplifies adding more quoting symbols if needed (at the expense of one more capturing group)
You can also try this:
String str = "This is a string that \"will be\" highlighted when your 'regular expression' matches something";
String ss[] = str.split("\"|\'");
for (int i = 0; i < ss.length; i++) {
if ((i % 2) == 0) {//even
String[] part1 = ss[i].split(" ");
for (String pp1 : part1) {
System.out.println("" + pp1);
}
} else {//odd
System.out.println("" + ss[i]);
}
}
The following returns an array of arguments. Arguments are the variable 'command' split on spaces, unless included in single or double quotes. The matches are then modified to remove the single and double quotes.
using System.Text.RegularExpressions;
var args = Regex.Matches(command, "[^\\s\"']+|\"([^\"]*)\"|'([^']*)'").Cast<Match>
().Select(iMatch => iMatch.Value.Replace("\"", "").Replace("'", "")).ToArray();
When you come across this pattern like this :
String str = "2022-11-10 08:35:00,470 RAV=REQ YIP=02.8.5.1 CMID=caonaustr CMN=\"Some Value Pyt Ltd\"";
//this helped
String[] str1= str.split("\\s(?=(([^\"]*\"){2})*[^\"]*$)\\s*");
System.out.println("Value of split string is "+ Arrays.toString(str1));
This results in :[2022-11-10, 08:35:00,470, PLV=REQ, YIP=02.8.5.1, CMID=caonaustr, CMN="Some Value Pyt Ltd"]
This regex matches spaces ONLY if it is followed by even number of double quotes.

Splitting a string into two

I am attempting to split a word from its punctuation:
So for example if the word is "Hello?". I want to store "Hello" in one variable and the "?" in another variable.
I tried using .split method but deletes the delimiter (the punctuation) , which means you wouldn't conserve the punctuation character.
String inWord = "hello?";
String word;
String punctuation = null;
if (inWord.contains(","+"?"+"."+"!"+";")) {
String parts[] = inWord.split("\\," + "\\?" + "\\." + "\\!" + "\\;");
word = parts[0];
punctuation = parts[1];
} else {
word = inWord;
}
System.out.println(word);
System.out.println(punctuation);
I am stuck I cant see another method of doing it.
Thanks in advance
You could use a positive lookahead to split so you don't actually use the punctuation to split, but the position right before it:
inWord.split("(?=[,?.!;])");
ideone demo
Further to the other suggestions, you can also use the 'word boundary' matcher '\b'. This may not always match what you are looking for, it detects the boundary between a word and a non-word, as documented: http://docs.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html
In your example, it works, though the first element in the array will be a blank string.
Here is some working code:
String inWord = "hello?";
String word;
String punctuation = null;
if (inWord.matches(".*[,?.!;].*")) {
String parts[] = inWord.split("\\b");
word = parts[1];
punctuation = parts[2];
System.out.println(parts.length);
} else {
word = inWord;
}
System.out.println(word);
System.out.println(punctuation);
You can see it running here: http://ideone.com/3GmgqD
I've also fixed your .contains to use .matches instead.
I think you can use the below regex. But not tried. Give it a try.
input.split("[\\p{P}]")
You could use substring here. Something like this:
String inWord = "hello?";
String word = inWord.substring (0, 5);
String punctuation = inWord.substring (5, inWord.length ());
System.out.println (word);
System.out.println (punctuation);

Checking if String contains another whole String

So, I've been trying to find online if there's a way to have a String be search for another whole string in java. Unfortunately, I haven't found anything that works.
What I mean is this:
String str = "this is a test";
If I search for this is it should return true. But if I search for this i it should be false.
I've tried using String.matches(), but that won't work because some of the strings being search may have a [, ], ?, etc in it - which would throw it off. Using String.indexOf(search) != -1 won't work either because it would return true for partial words.
Use \b, the zero-width word boundary delimiter, in a regex.
String str = "this is a test";
String search = "this is";
Pattern p = Pattern.compile(String.format("\\b%s\\b", Pattern.quote(search)));
boolean matches = p.matcher(Pattern.quote(str)).find();
If you are also separate words from non alphabetic character and not only whitespaces you can use lookaround mechanisms. Try maybe this way
String str = "[this] is...";
String search = "[this] is";
Pattern p = Pattern.compile("(?!<\\p{IsAlphabetic})"
+ Pattern.quote(search) + "(?!\\p{IsAlphabetic})");
boolean matches = p.matcher(str).find();
It will check if matched part has no alphabetic characters before or after it.
Note: \\p{IsAlphabetic} includes all Unicode alphabetic characters like ż ź ć, not only a-z A-Z range.

Regarding String manipulation

I have a String str which can have list of values like below. I want the first letter in the string to be uppercase and if underscore appears in the string then i need to remove it and need to make the letter after it as upper case. The rest all letter i want it to be lower case.
""
"abc"
"abc_def"
"Abc_def_Ghi12_abd"
"abc__de"
"_"
Output:
""
"Abc"
"AbcDef"
"AbcDefGhi12Abd"
"AbcDe"
""
Well, without showing us that you put any effort into this problem this is going to be kinda vague.
I see two possibilities here:
Split the string at underscores, apply the answer from this question to each part and re-combine them.
Create a StringBuilder, walk through the string and keep track of whether you are
at the start of the string
after an underscore or
somewhere else
and act appropriately on the current character before appending it to the StringBuilder instance.
replace _ with space (str.replace("_", " "))
use WordUtils.capitalizeFully(str); (from commons-lang)
replace space with nothing (str.replace(" ", ""))
You can use following regexp based code:
public static String camelize(String input) {
char[] c = input.toCharArray();
Pattern pattern = Pattern.compile(".*_([a-z]).*");
Matcher m = pattern.matcher(input);
while ( m.find() ) {
int index = m.start(1);
c[index] = String.valueOf(c[index]).toUpperCase().charAt(0);
}
return String.valueOf(c).replace("_", "");
}
Use Pattern/Matcher in the java.util.regex package:
for each string that is in your array do the following:
StringBuffer output = new StringBuffer();
Matcher match = Pattern.compile("[^|_](\w)").matcher(inStr);
while(match.find()) {
match.appendReplacement(output, matcher.match(0).ToUpper());
}
match.appendTail(output);
// Will have the properly capitalized string.
String capitalized = output.ToString();
The regular expression looks for either the start of the string or an underscore "[^|_]"
Then puts the following character into a group "(\w)"
The code then goes through each of the matches in the input string capitalizing the first satisfying group.

Categories

Resources