Uppercase all characters but not those in quoted strings - java

I have a String and I would like to uppercase everything that is not quoted.
Example:
My name is 'Angela'
Result:
MY NAME IS 'Angela'
Currently, I am matching every quoted string then looping and concatenating to get the result.
Is it possible to achieve this in one regex expression maybe using replace?

List<String> matchList = new ArrayList<String>();
Pattern regex = Pattern.compile("\\'(.*?)\\'");
String input = "'s'Hello This is 'Java' Not '.NET'";
Matcher regexMatcher = regex.matcher(input);
StringBuffer sb = new StringBuffer();
int counter = 0;
while (regexMatcher.find())
{// Finds Matching Pattern in String
regexMatcher.appendReplacement(sb, "{"+counter+"}");
matchList.add(regexMatcher.group());// Fetching Group from String
counter++;
}
String format = MessageFormat.format(sb.toString().toUpperCase(), matchList.toArray());
System.out.println(input);
System.out.println("----------------------");
System.out.println(format);
Input: 's'Hello This is 'Java' Not '.NET'
Output: 's'HELLO THIS IS 'Java' NOT '.NET'

You could use a regular expression like this:
([^'"]+)(['"]+[^'"]+['"]+)(.*)
# match and capture everything up to a single or double quote (but not including)
# match and capture a quoted string
# match and capture any rest which might or might not be there.
This will only work with one quoted string, obviously. See a working demo here.

Ok. This will do it for you.. Not efficient, but will work for all cases. I actually don't suggest this solution as it will be too slow.
public static void main(String[] args) {
String s = "'Peter' said, My name is 'Angela' and I will not change my name to 'Pamela'.";
Pattern p = Pattern.compile("('\\w+')");
Matcher m = p.matcher(s);
List<String> quotedStrings = new ArrayList<>();
while(m.find()) {
quotedStrings.add(m.group(1));
}
s=s.toUpperCase();
// System.out.println(s);
for (String str : quotedStrings)
s= s.replaceAll("(?i)"+str, str);
System.out.println(s);
}
O/P :
'Peter' SAID, MY NAME IS 'Angela' AND I WILL NOT CHANGE MY NAME TO 'Pamela'.

Adding to the answer by #jan_kiran, we need to call the
appendTail()
method appendTail(). Updated code is:
List<String> matchList = new ArrayList<String>();
Pattern regex = Pattern.compile("\\'(.*?)\\'");
String input = "'s'Hello This is 'Java' Not '.NET'";
Matcher regexMatcher = regex.matcher(input);
StringBuffer sb = new StringBuffer();
int counter = 0;
while (regexMatcher.find())
{// Finds Matching Pattern in String
regexMatcher.appendReplacement(sb, "{"+counter+"}");
matchList.add(regexMatcher.group());// Fetching Group from String
counter++;
}
regexMatcher.appendTail(sb);
String formatted_string = MessageFormat.format(sb.toString().toUpperCase(), matchList.toArray());

I did not find my luck with these solutions, as they seemed to remove trailing non-quoted text.
This code works for me, and treats both ' and " by remembering the last opening quotation mark type. Replace toLowerCase appropriately, of course...
Maybe this is extremely slow; I don't know:
private static String toLowercaseExceptInQuotes(String line) {
StringBuffer sb = new StringBuffer(line);
boolean nowInQuotes = false;
char lastQuoteType = 0;
for (int i = 0; i < sb.length(); ++i) {
char cchar = sb.charAt(i);
if (cchar == '"' || cchar == '\''){
if (!nowInQuotes) {
nowInQuotes = true;
lastQuoteType = cchar;
}
else {
if (lastQuoteType == cchar) {
nowInQuotes = false;
}
}
}
else if (!nowInQuotes) {
sb.setCharAt(i, Character.toLowerCase(sb.charAt(i)));
}
}
return sb.toString();
}

Related

Java Replace substring in String with exact number of character

My string is "test"
"test" has 4 characters
I want to replace "test" with "****"
so I get "****"
My code
System.out.println("_test_");
System.out.println("_test_".replaceAll("test", "*"));
But it replace test with 1 *.
If the word test is just an example, you may use Matcher.appendReplacement (see How to appendReplacement on a Matcher group instead of the whole pattern? for more details on this technique):
String fileText = "_test_";
String pattern = "test";
Pattern r = Pattern.compile(pattern);
Matcher m = r.matcher(fileText);
StringBuffer sb = new StringBuffer();
while (m.find()) {
m.appendReplacement(sb, repeat("*", m.group(0).length()));
}
m.appendTail(sb); // append the rest of the contents
System.out.println(sb);
And the repeat function (borrowed from Simple way to repeat a String in java, see other options there) SO post is:
public static String repeat(String s, int n) {
if(s == null) {
return null;
}
final StringBuilder sb = new StringBuilder(s.length() * n);
for(int i = 0; i < n; i++) {
sb.append(s);
}
return sb.toString();
}
See IDEONE demo
If you have an arbitrary text to be replaced, and you want to use replaceAll(), be aware that it takes a regular expression, and various characters have special meaning. To prevent issues, call Pattern.quote().
Also, to replace with a sequence of * of equal length, you need to build a string of such.
Here is a nice short method for doing it:
private static String mask(String input, String codeword) {
char[] buf = new char[codeword.length()];
Arrays.fill(buf, '*');
return input.replaceAll(Pattern.quote(codeword), new String(buf));
}
Test
System.out.println(mask("_test_", "test"));
System.out.println(mask("This is his last chance", "is"));
Output
_****_
Th** ** h** last chance
Yes, because replaceAll(str1, str2) will replace all occurrences of str1 with str2. Since you are using literals, you need to say
System.out.println("_test_".replaceAll("test", "****"));
If you want your own replacement function you can do something like this:
public static String replaceStringWithChar(String src, String seek, char replacement)
{
StringBuilder sb = new StringBuilder();
for(int i = 0; i < seek.length(); i++) sb.append(replacement);
return src.replaceAll(seek, sb.toString());
}
You would then call it like so:
replaceStringWithChar("_test_", "test", '*');
So I got the answer and I was really looking for
something with as few line as possible. Thank you all
for the answer but this is the answer I found most useful.
I apologize for not being clear in the question, if I was not.
String str1 = "_AnyString_";
int start_underscore = str1.indexOf("_");
int end_underscore = str1.indexOf("_", start_underscore + 1);
String str_anything = str1.substring(start_underscore + 1, end_underscore);
String str_replace_asterisk = str_anything.replaceAll(".", "*");
System.out.println(str_replace_asterisk);
str1 = str1.replace(str_anything, str_replace_asterisk);
System.out.println(str1);
Output:
_AnyString_
_*********_
Actually you are pretty close the what you want. This is what you can do:
System.out.println("_test_".replaceAll("[test]", "*"));
System.out.println("hello".replaceAll("[el]", "*"));
Output:
_****_
h***o

Is there a way to use replaceAll on string but call method for replacing the text on each occurrence of a match

I want to replace all occurrences of particular string with different UUID's. For example,
content = content.replaceAll("xyz", "xyz" + generateUUID());
but problem here is that all the "xyz"'s will get replaced by same UUID. But I want that each "xyz" gets replaced by an individual unique ID. How can this be done?
You can do this using Matcher.appendReplacement. This will give you the replaceAll functionality of a complete regex (not just a static String). Here, I use uidCounter as a very simple generateUUID; you should be able to adapt this to your own generateUUID function.
public class AppendReplacementExample {
public static void main(String[] args) throws Exception {
int uidCounter = 1000;
Pattern p = Pattern.compile("xyz");
String test = "abc xyz def xyz ghi xyz";
Matcher m = p.matcher(test);
StringBuffer sb = new StringBuffer();
while(m.find()) {
m.appendReplacement(sb, m.group() + uidCounter);
uidCounter++;
}
m.appendTail(sb);
System.out.println(sb.toString());
}
}
Output:
abc xyz1000 def xyz1001 ghi xyz1002
You could use a StringBuilder (for efficiency, since String is immutable), a while loop and something like
// content = content.replaceAll("xyz", "xyz" + generateUUID());
StringBuilder sb = new StringBuilder(content);
String toReplace = "xyz";
int toReplaceLen = toReplace.length();
int pos;
while ((pos = sb.indexOf(toReplace)) > -1) {
sb.replace(pos, pos + toReplaceLen, generateUUID());
}
// content = sb.toString(); // <-- if you want to use content.
It looks like you'd like a way to say something like this:
content = content.replaceAll("xyz", x -> x + generateUUID());
Here's an adaptation of durron597's answer that lets you do almost that:
content = replaceAll(content, "xyz", x -> x + generateUUID());
public static String replaceAll(String source, String regex,
Function<String, String> replacement) {
StringBuffer sb = new StringBuffer();
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(source);
while (matcher.find()) {
matcher.appendReplacement(sb, replacement.apply(matcher.group(0)));
}
matcher.appendTail(sb);
return sb.toString();
}

java regular expression find and replace

I am trying to find environment variables in input and replace them with values.
The pattern of env variable is ${\\.}
Pattern myPattern = Pattern.compile( "(${\\.})" );
String line ="${env1}sojods${env2}${env3}";
How can I replace env1 with 1 and env2 with 2 and env3 with 3, so
that after this I will have a new string 1sojods23?
Strings in Java are immutable, which makes this somewhat tricky if you are talking about an arbitrary number of things you need to find and replace.
Specifically you need to define your replacements in a Map, use a StringBuilder (before Java 9, less performant StringBuffer should have been used) and the appendReplacements() and appendTail() methods from Matcher. The final result will be stored in your StringBuilder (or StringBuffer).
Map<String, String> replacements = new HashMap<String, String>() {{
put("${env1}", "1");
put("${env2}", "2");
put("${env3}", "3");
}};
String line ="${env1}sojods${env2}${env3}";
String rx = "(\\$\\{[^}]+\\})";
StringBuilder sb = new StringBuilder(); //use StringBuffer before Java 9
Pattern p = Pattern.compile(rx);
Matcher m = p.matcher(line);
while (m.find())
{
// Avoids throwing a NullPointerException in the case that you
// Don't have a replacement defined in the map for the match
String repString = replacements.get(m.group(1));
if (repString != null)
m.appendReplacement(sb, repString);
}
m.appendTail(sb);
System.out.println(sb.toString());
Output:
1sojods23
I know this is old, I was myself looking for a, appendReplacement/appendTail example when I found it; However, the OP's question doesn't need those complicated multi-line solutions I saw here.
In this exact case, when the string to replace holds itself the value we want to replace with, then this could be done easily with replaceAll:
String line ="${env1}sojods${env2}${env3}";
System.out.println( line.replaceAll("\\$\\{env([0-9]+)\\}", "$1") );
// Output => 1sojods23
DEMO
When the replacement is random based on some conditions or logic on each match, then you can use appendReplacement/appendTail for example
Hopefully you would find this code useful:
Pattern phone = Pattern.compile("\\$\\{env([0-9]+)\\}");
String line ="${env1}sojods${env2}${env3}";
Matcher action = phone.matcher(line);
StringBuffer sb = new StringBuffer(line.length());
while (action.find()) {
String text = action.group(1);
action.appendReplacement(sb, Matcher.quoteReplacement(text));
}
action.appendTail(sb);
System.out.println(sb.toString());
The output is the expected: 1sojods23.
This gives you 1sojods23:
String s = "${env1}sojods${env2}${env3}";
final Pattern myPattern = Pattern.compile("\\$\\{[^\\}]*\\}");
Matcher m = myPattern.matcher(s);
int i = 0;
while (m.find()) {
s = m.replaceFirst(String.valueOf(++i));
m = myPattern.matcher(s);
}
System.out.println(s);
and this works too:
final String re = "\\$\\{[^\\}]*\\}";
String s = "${env1}sojods${env2}${env3}";
int i = 0;
String t;
while (true) {
t = s.replaceFirst(re, String.valueOf(++i));
if (s.equals(t)) {
break;
} else {
s = t;
}
}
System.out.println(s);
You can use a StringBuffer in combination with the Matcher appendReplacement() method, but if the the pattern does not match, there is no point in creating the StringBuffer.
For example, here is a pattern that matches ${...}. Group 1 is the contents between the braces.
static Pattern rxTemplate = Pattern.compile("\\$\\{([^}\\s]+)\\}");
And here is sample function that uses that pattern.
private static String replaceTemplateString(String text) {
StringBuffer sb = null;
Matcher m = rxTemplate.matcher(text);
while (m.find()) {
String t = m.group(1);
t = t.toUpperCase(); // LOOKUP YOUR REPLACEMENT HERE
if (sb == null) {
sb = new StringBuffer(text.length());
}
m.appendReplacement(sb, t);
}
if (sb == null) {
return text;
} else {
m.appendTail(sb);
return sb.toString();
}
}
Map<String, String> replacements = new HashMap<String, String>() {
{
put("env1", "1");
put("env2", "2");
put("env3", "3");
}
};
String line = "${env1}sojods${env2}${env3}";
String rx = "\\$\\{(.*?)\\}";
StringBuffer sb = new StringBuffer();
Pattern p = Pattern.compile(rx);
Matcher m = p.matcher(line);
while (m.find()) {
// Avoids throwing a NullPointerException in the case that you
// Don't have a replacement defined in the map for the match
String repString = replacements.get(m.group(1));
if (repString != null)
m.appendReplacement(sb, repString);
}
m.appendTail(sb);
System.out.println(sb.toString());
In the above example we can use map with just key and values --keys can be env1 ,env2 ..
Use groups once it is matched ${env1} will be your first group and then you use regex to replace what is in each group.
Pattern p = Pattern.compile("(${\\.})");
Matcher m = p.matcher(line);
while (m.find())
for (int j = 0; j <= m.groupCount(); j++)
//here you do replacement - check on the net how to do it;)

Insert a character before and after all letters in a string in Java

I want to insert a % character before after every letter in a string, but using StringBuilder to make it fast.
For example, if a string is 'AA' then it would be '%A%A%'. If it is 'XYZ' then it would be '%X%Y%Z%'
String foo = "VWXYZ";
foo = "%" + foo.replaceAll("(.)","$1%");
System.out.println(foo);
Output:
%V%W%X%Y%Z%
You don't need a StringBuilder. The compiler will take care of that simple concatenation prior to the regex for you by using one.
Edit in response to comment below:
replaceAll() uses a Regular Expression (regex).
The regex (.) says "match any character, and give me a reference to it" . is a wildcard for any character, the parenthesis create the backreference. The $1 in the second argument says "Use backreference #1 from the match".
replaceAll() keeps running this expression over the whole string replacing each character with itself followed by a percent sign, building a new String which it then returns to you.
Try something like this:
String test = "ABC";
StringBuilder builder = new StringBuilder("");
builder.append("%");
for (char achar : test.toCharArray()) {
builder.append(achar);
builder.append("%");
}
System.out.println(builder.toString());
public static String escape(String s) {
StringBuilder buf = new StringBuilder();
boolean wasLetter = false;
for (char c: s.toCharArray()) {
boolean isLetter = Character.isLetter(c);
if (isLetter && !wasLetter) {
buf.append('%');
}
buf.append(c);
if (isLetter) {
buf.append('%');
}
wasLetter = isLetter;
}
return buf.toString();
}
StringBuilder sb = new StringBuilder("AAAAAAA");
for(int i = sb.length(); i >= 0; i--)
{
sb.insert(i, '%');
}
You may see this.
String s="AAAA";
StringBuilder builder = new StringBuilder();
char[] ch=s.toCharArray();
for(int i=0;i<ch.length;i++)
{
builder.append("%"+ch[i]);
}
builder.append("%");
System.out.println(builder.toString());
Output
%A%A%A%A%
I agree with #Brian Roach to add character to before and after but if you want to add any specific character then do like this
String source = "hello good old world";
StringBuffer res = new StringBuffer();
String[] strArr = tagList.split(" ");
for (String str : strArr) {
char[] stringArray = str.trim().toCharArray();
stringArray[0] = stringArray[0];
str = new String(stringArray);
//here you need to specify your first and last character which you want to set
res.append("#"+ str + "$").append(" ");
}
System.out.println("Result: " + res.toString().trim());
Output :- #hello$ #good$ #old$ #world$

find substrings inside string

How can i find substrings inside string and then remember and delete it when i found it.
EXAMPLE:
select * from (select a.iid_organizacijske_enote,
a.sifra_organizacijske_enote "Sifra OE",
a.naziv_organizacijske_enote "Naziv OE",
a.tip_organizacijske_enote "Tip OE"
I would like to get all word inside " ", so
Sifra OE
Naziv OE
TIP OE
and return
select * from (select a.iid_organizacijske_enote,
a.sifra_organizacijske_enote,
a.naziv_organizacijske_enote,
a.tip_organizacijske_enote
i try with regex, indexOf() but no one works ok
String.replace(..):
Replaces each substring of this string that matches the literal target sequence with the specified literal replacement sequence. The replacement proceeds from the beginning of the string to the end, for example, replacing "aa" with "b" in the string "aaa" will result in "ba" rather than "ab".
str = str.replace(wordToRemove, "");
If you don't know the words in advance, you can use the regex version:
str = str.replaceAll("\"[^\"]+\"", "");
This means, that all strings starting and ending with quotes, with any character except quotes between them, will be replaced with empty string.
Consider using regex with capturing groups. With Java's Matcher class, you can find the first match, and then use replaceFirst(String).
--EDIT--
example (not efficient for long inputs):
String in = "hello \"there\", \"friend!\"";
Pattern p = Pattern.compile("\\\"([^\"]*)\\\"");
Matcher m = p.matcher(in);
while(m.find()){
System.out.println(m.group(1));
in = m.replaceFirst("");
m = p.matcher(in);
}
System.out.println(in);
i tried and created function as below -- its working fine and returning output you want
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Program p = new Program();
string s = p.mystring("select * from (select a.iid_organizacijske_enote, a.sifra_organizacijske_enote 'Sifra OE', "
+"a.naziv_organizacijske_enote 'Naziv OE', "+
"a.tip_organizacijske_enote 'Tip OE'");
}
public string mystring(string s)
{
if (s.IndexOf("'") > 0)
{
string test = s.Substring(0, s.IndexOf("'"));
s = s.Replace(test+"'", "");
s = s.Remove(0, s.IndexOf("'") + 1);
test = test.Replace("'", "");
test = test + s;
return mystring(test);
}
else
{
return s;
}
}
}
}
best & optimized code is here:
public static void main(String[] args){
int j =0;
boolean substr = true;
String mainStr = "abcdefgh";
String ipStr = "efg";
for(int i=0 ; i < mainStr.length();i++){
if(j<ipStr.length() && mainStr.charAt(i)==ipStr.charAt(j)){
j++;
}
}
if(j>=0 && j !=ipStr.length()){
substr = false;
}
System.out.println("its a substring:"+substr);
}

Categories

Resources