1

Suppose I have the following file called Product.java:

public class Product {
    public String name;
    public String description;
    public String picture;
    public double price;

    public Product(String name, String description, String picture, double price) {
        this.name = name;
        this.description = description;
        this.picture = picture;
        this.price = price;
    }

    public String getName() {
        return this.name;
    }

    public String getDescription() {
        return this.description;
    }

    public String getPicture() {
        return this.picture;
    }

    public double getPrice() {
        return this.price;
    }

    public String toString() {
        return "Product";
    }
}

What I am currently trying to do is to replace instances of public with private for the class fields only in Product.java, updating the file in place. So, after replacement, the file should look like:

public class Product {
    private String name;
    private String description;
    private String picture;
    private double price;
    ...
    ...
    ...
}

I tried doing this by using sed with the following statement:

sed -ri 's/public [a-zA-Z a-z]*;/private/' Product.java

However, this just replaces the class fields to just private. Due to this, I was wondering how do I just replace the public part of the lines with private while keeping the rest of the line unchanged? I'm unsure how to accomplish this behavior. Any feedback or suggestions would be greatly appreciated.

2
  • 1
    Try sed -ri 's/public ([a-zA-Z a-z]*;)/private \1/' Product.java
    – user232326
    May 17, 2021 at 5:08
  • @Isaac Thank you. I didn't realize I could use \1 to back reference. It is super helpful to know for future reference. May 17, 2021 at 5:31

1 Answer 1

0

ImHere already told you how to solve that very problem by referring to parts of the pattern in the replacement, but I'd like to add some useful hints:

  • Don't use -r for extended regular expression syntax (btw, your original command didn't make use of it anyhow). -E is the portable option.
  • Always think about whether all possible cases are covered. What about public int[] foo or public String description2 or line breaks between public and ;?
  • Sometimes it better to exclude cases by an inverted address like sed '/{/!s/public /private /'which replaces all public unless there is a { on that line
  • Finally think about false positives like a comment // don't allow a public setter for this member; it can only be set on instanisation or some (in this case stupid edge) case with a variable called republic, so your pattern should better be ^[[:space:]]*public

Together, a more robust script could look like

sed '/{/!s/^\([[:space:]]*\)public /\1private /'

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.