Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations TouchToneTommy on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Strings - Find and Replace 4

Status
Not open for further replies.

timesign

Programmer
May 7, 2002
53
US
Hi,
I am looking for a java util to do find and replace on strings. Java API has String(char, char). I am looking for replacing within a string every occurence of a string with another string. example;

"Run Jim Run"

replace "Run" with "See"

"See Jim See"

Thanks
 
How about this?

/**
* Replaces the first occurence of a substring
* @param source string that needs to have stuff replaced
* @param oldVal name of variable in Source string
* @param newVal replacement to put in String
*/
public static String replace(String source, String oldVal, String newVal)
{
if (oldVal == null) return source;

//cat.debug("replacing:" + oldVal + ": by :" + newVal + ":");
StringBuffer SB = new StringBuffer(source);
int nameindex = source.indexOf(oldVal);
SB.replace(nameindex, nameindex + oldVal.length(), newVal);
//cat.debug("new StringBuffer: "+SB);
return new String(SB);
}

/**
* Replaces all occurences of a substring
* @param source string that needs to have stuff replaced
* @param oldVal name of variable in Source string
* @param newVal replacement to put in String
*/
public static String replaceAll(String source, String oldVal, String newVal)
{
while(source.indexOf(oldVal) != -1)
{
source = replace(source, oldVal, newVal);
}
return source;
}
 
Frankly, I don’t fully understand all of the code but it works beautifully!!!!
If you have the time and don’t mind briefly explaining how you did it in so few lines of code, I would be interested.
Thanks a load
 
Code:
    while(source.indexOf(oldVal) != -1)
    {
      source = replace(source, oldVal, newVal);
    }

the while loop basically just makes sure that all occurences of the string are handled.

Code:
      StringBuffer SB = new StringBuffer(source);
    int nameindex = source.indexOf(oldVal);
    SB.replace(nameindex, nameindex + oldVal.length(), newVal);

SB is a StringBuffer of source,
source.indexOf(oldVal) returns the index of the first character of the instance of the search string.

replace(int StartPosition, int StopPosition, String NewString)

so basically replace from StartPosition to Stop position with whatever is in NewString

Hope that helps..
Martin
If the sky is blue and the Sun is yellow.... Why isn't the air Green?
 
Just a little FYI. The replaceAll method will go into an infinite loop if the newStr contains the oldStr. For instance: If you have the String "Just a little demo", and you set "a" as the old string and "an" as the new string, you will never get returned to, as the string "a" is always present in the resulting string.

-gc
 
godcomplex => this is why I post my work. Thanks, that's worth a star!

While it is something I developed for situations where it is impossible to have such a loop, I should revise that to make it more general, or actually copy code from the JDK 1.4. It's unfortunately not my decision to upgrade.

As for a bit more of the explanation of how it works...

source.indexOf(oldVal) returns -1 if no occurence of oldVal is found in source. So in plain english, that while loop means: "While there is still an occurence of the oldVal string in the source string, replace the first occurence of oldVal with newVal".
 
Daniel 135=> Do you have a fixed version of the code available? Thanks---
 
sorry, I don't. I would recommend upgrading to Java 1.4 if at all feasible.

I can't yet, so I'm sticking with this code, however much of an ugly patch it may be. It is only used for replacement on variables such as $DATE$, where there is no risk of encountering an infinite loop.

If you can't upgrade, there are a couple ways you could rewrite it. I thought of using StringTokenizer, but we found a bug (when two tokens are next to each other) which makes it impossible to use. There are some PERL libraries that were used here for a while which took care of that problem, but we've lost that reference.

HTH
 
Little perl program:

----replace-------
while ($line=<>) {
$line =~ s/oldVal/newVal/;
}
-------------------

----replaceall----
while ($line=<>) {
$line =~ s/oldVal/newVal/g;
}
-------------------

Be careful - 'oldVal' is the regular expression!
Hope this helps!
 
Try this one:

public static String Replace(String source, String from, String to)
{
StringBuffer sb = new StringBuffer();
int oldIndex=0, newIndex;
while (-1 != (newIndex = source.indexOf(from,oldIndex)))
{
sb.append(source.substring(oldIndex,newIndex)).append(to);
oldIndex=newIndex+from.length();
}
if (oldIndex < source.length())
sb.append(source.substring(oldIndex));
return sb.toString();
}

HTH

Pieter
 
PieterWinter, suppose I have Source = &quot;abcdefg&quot;, From = &quot;c&quot;, and To = &quot;ZZZ&quot;.

When the while loop comes up, newIndex = 2 pointing to the &quot;c&quot;. Then we append Source from 0 to 2, noninclusive (&quot;ab&quot;) to To. sb = &quot;abZZZ&quot;.

I believe there is a problem with the next line. You move oldIndex to newIndex + from.length(), in this case 5. When we loop around and examine the Source string again, we are looking at &quot;e&quot;, completely skipping &quot;d&quot;. This is only a problem when To and From are different lengths. In certain cases, if From.length() > To.length(), an infinite loop will result.

I think it would be necessary to keep separate indices for the leftmost position in Source and sb. This preserves a character-by-character evaluation of the Source string while letting you piece together the buffer.
 
segmentationfault,

You wrote:
&quot;I believe there is a problem with the next line. You move oldIndex to newIndex + from.length(), in this case 5.&quot;

This is not true. When newIndex = 2, and the from.length() equals 1, the oldIndex becomes 3, not 5. This means that the search continues from d.

Running the test on your string produces the output
abZZZdefg

Regards,
Pieter
 
Eh heh... <nervous laugh>

You're absolutely right. My mistake was in confusing from.length() with to.length() when updating oldIndex. Why can't we delete these posts! Darnit.
 
Did anyone notice DJSmith back there pointing out that there is now a String.replaceAll(String,String) method in 1.4?

There are also regular expressions. Jeremy Nicholson, Director of a UK-based Java and Data Warehousing consultancy
 
Yeah, J2SE 1.4 has some nice features... too bad most people doing Java development can't use 1.4 yet.

If you are doing J2EE work then you will need to wait until your Application Server supports J2SE 1.4. This probably won't be until implementations of J2EE 1.4 (which requires the use of J2SE 1.4) start popping up around December. Tack an extra 6 - 9 months for good luck (except for early adopters) and it looks like another year or so until major market acceptance of J2SE 1.4.

Sorry, I've wasted enough space with annoying acronyms.
 
lol... yeah, still that's exactly the situation I'm in... would really like to use the nice features in 1.4, but can't (using WebLogic).

PieterWinter- thanks for this (you get a star!). I knew my version had a bug in it (not at all likely to affect us though), but just haven't had the time to sit down and think about it.
 
hello daniel,

I've just written some code to do the same as u want as the replaceAll in 1.4 doesnt work the way i want. Here it is but I havent fully tested it for when you are replacing a string with a shorter string, but it seems ok so far....


Code:
    public String myReplaceAll(String input, String replace, String with)
    {
        String firstHalf;
        String secondHalf;
        String newString;
        
        for(int i =0 ; i < input.length() ; i++)
        {
            int startOfReplaceable = input.indexOf(replace, i);
            if(startOfReplaceable != -1)
            {
                firstHalf = input.substring(0 , (startOfReplaceable));
                secondHalf = input.substring((startOfReplaceable + replace.length()) , input.length());
                input = firstHalf + with + secondHalf;
                
                System.out.println(i+ &quot; &quot; + input);
                if(replace.length() < with.length())            //if replaceing with LONGER string
                {
                    if(i == 0)
                    { 
                        
                    }else if(input.charAt(i) == input.charAt(i-1)){
                        i = i+ with.length()-replace.length();   
                    }else{
                        i = i+ with.length();
                    }
                }else if(replace.length() > with.length())      //if replaceing with SHORTER string
                {
                    if(i == 0)
                    { 
                        
                    }else{
                        i = i- replace.length();
                    }
                }
            }
        }
        return input;
    }
 
Yet another way, kinda like Pieter's:

Code:
public static String replaceAll2( String target, 
                                  String str,
                                  String replacement )
{
   int pos = target.indexOf( str ); // first match

   if ( pos < 0 )    return target;

   final int len = str.length();
   final int replaceLen = replacement.length();
   final int targetLen = target.length();
   int lastPos = 0;

   final char [] ara = target.toCharArray();
   StringBuffer buf = new StringBuffer();

   while ( pos > -1 ) // found BLAH in AAA_BLAH_BBB
   {
      buf.append( ara, lastPos, (pos - lastPos) ); // AAA_
      buf.append( replacement ); // replace BLAH

      lastPos = pos + len;
      pos = (lastPos < targetLen) ? 
                      target.indexOf(str, lastPos) 
                    : -1;
   }

   if ( lastPos < targetLen )
         buf.append( ara, lastPos, (targetLen - lastPos) );
   return buf.toString();
}
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top