简体   繁体   中英

How do I replace a substring that occurs after a certain number of spaces in a string?

I'm extracting data from a file in this format:

`1111 1.0 2222 53.5 3333 0.3 4444 541.1 5555 0.3'

Now suppose I want to replace 0.3 with 32.2 . How do I best go about it in Java?

I thought of using str.replaceAll(str.substring(beginIndex, endIndex), replacement) . However, it requires a beginning and end Index, which I can't easily provide.

What's the best method in Java?

EDIT: there may be multiple instances of 0.3. I only wish to change the one that occurs after a certain no. of spaces. This one occurs after 5 spaces, for example.

The following in concise and dynamically adaptable. I instantiated variables to provide an example, but the crucial parts are the first and last lines of the code:

String regex = "(?<=\\s{%s})%s(?=\\s{%s})";
String numSpaces = "1";
String number = "0.3";
String replacement = "32.2";
String yourString = "1111 1.0 2222 53.5 3333 0.3 4444 541.1";
yourString = yourString.replaceAll(String.format(regex, numSpaces, number, numSpaces),
                                   replacement);
System.out.println(yourString);
//prints 1111 1.0 2222 53.5 3333 32.2 4444 541.1

In this example, "(?<=\\\\s{%s})%s(?=\\\\s{%s})" would become: (?<=\\\\s{1})0.3(?=\\\\s{1})
which means "0.3" with one whitespace tokens before and after, it takes advantage of positive look behinds and aheads so that only the number is replaced and the spaces are left the same.

Also, note that replaceAll() should only be used when dealing with regular expressions. If you're not using regular expressions, use .replace() instead. .replace() replaces all instances, too, the name is slightly misleading.

Note, if the number of spaces before and after are supposed to be different, just change the final argument to String.format() to be whatever number of spaces should be after the number.

EDIT :
Apparently we're defining spaces differently. I assumed that a certain number of spaces literally means a certain number of spaces before and after the number in question.

Try,

  String str="1111 1.0 2222 53.5 3333 0.3 4444 541.1 ";

  str=str.replaceAll(" 0.3 ", " 32.2 ");    
  System.out.println(str);

Assuming you want to replace ALL of the 0.3 s in your String ( tested and works ):

String s = "1111 1.0 2222 53.5 3333 0.3 4444 541.1";

// replace "0.3 " at the beginning of the String
if (s.substring(0,4).equals("0.3 "))
    s = "32.2" + s.substring(3);

// replace " 0.3" at the end of the String
if (s.substring(s.length() - 4).equals(" 0.3"))
    s = s.substring(0, s.length() - 4) + " 32.2";

// replace all the rest of the "0.3" in the String
s = s.replaceAll(" 0.3 ", " 32.2 ");

Input/Output:

Input:

"1111 1.0 2222 53.5 3333 0.3 4444 541.1"

Output:

"1111 1.0 2222 53.5 3333 32.2 4444 541.1"

Input:

"0.3 1111 1.0 2222 53.5 3333 0.3 4444 541.1 0.3"

Output:

"32.2 1111 1.0 2222 53.5 3333 32.2 4444 541.1 32.2"

Input:

"0.35 1111 1.0 2222 53.5 3333 0.3 4444 540.3"

Output:

"0.35 1111 1.0 2222 53.5 3333 32.2 4444 540.3"

Try using this regular expression, \\b0\\.3\\b .
\\b is a word boundary, which allows you to treat 0.3 as word.
0 is 0
\\. represents a dot literal. You have to escape the dot because a dot in regular expressions will match any character.
3 is a literal 3.

Remember in java you have to escape the backslash, so your final regular expression is this.

String regexp = "\\\\b0\\\\.3\\\\b";

Example Junit Test

package demo;
import static org.junit.Assert.*;
import org.junit.Test;

public class Matchy {
    String regexp = "\\b0\\.3\\b";
    @Test
    public void test() {
        String str = "0.3 0.2 123.4 0.3 0.3 013";   
        String result = str.replaceAll(this.regexp, "32.2");
        String expect = "32.2 0.2 123.4 32.2 32.2 013";
        assertEquals(str, expect, result);
    }
    @Test
    public void test2() {
        String str = "1111 1.0 2222 53.5 3333 0.3 4444 541.1";  
        String result = str.replaceAll(this.regexp, "32.2");
        String expect = "1111 1.0 2222 53.5 3333 32.2 4444 541.1";
        assertEquals(str, expect, result);
    }

}

I think this code should do what you want.

String str = "1111 1.0 2222 53.5 3333 0.3 4444 541.1 5555 0.3";
int numSpaces = 5;
String replacement = "32.2";
Matcher m = Pattern.compile("((?:\\S+\\s+){" + numSpaces + "})(\\S+)(.*)").matcher(str);
m.find();
System.out.println("replaced " + m.group(2) + " with " + replacement + " at index " + m.start(2));
System.out.println(m.group(1) + replacement + m.group(3));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM