cHam
cHam

Reputation: 2664

sed command not working from java

I am trying to run a sed command from java without success. Here is my java code:

String[] cmd = {"sed", "-i", "'"+lineIndex+"s/"+line+"/"+currentBid+"/g'", "/data/jsp/items.xml"};
        Runtime.getRuntime().exec(cmd);

I also tried:

String[] cmd = {"/bin/sh","-c","sed", "-i", "'"+lineIndex+"s/"+line+"/"+currentBid+"/g'", "/data/jsp/items.xml"};
        Runtime.getRuntime().exec(cmd);

Thing is, if I print out the contents of the cmd String and run it in a terminal it does work. It's just not executing it from java for some reason. Te make this more clear, when I run the command directly from a terminal the file "items.xml" changes. When I run it from java the file does not change. I've verified that the command is correct as sown below.

Am I missing something?

The output from cmd is sed -i '21s/2/102/g' /data/jsp/items.xml

** EDIT

I made the following changes based on comments below. No change in output however.

String[] cmd = {"/bin/sh","-c","sed", "-i", "'"+lineIndex+"s/"+line+"/"+currentBid+"/g'", "/data/jsp/items.xml"};
Process p = Runtime.getRuntime().exec(cmd);
p.waitFor();

BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line2 = reader.readLine();
while (line2 != null) {
     line2 = reader.readLine();
}
reader.close();

Upvotes: 3

Views: 3569

Answers (4)

Kirby
Kirby

Reputation: 15855

Honestly there is no need to externally execute sed in this case. Read the file in Java and use Pattern. Then you have code that could run on any platform. Combine this with org.apache.commons.io.FileUtils and you can do it in a few lines of code.

    final File = new File("/data/jsp/items.xml");    
    String contents = FileUtils.readFileToString(file, StandardCharsets.UTF_8.name());
    contents = Pattern.compile(line).matcher(contents).replaceAll(currentBid);
    FileUtils.write(file, contents);

Or, in a short, self-contained, correct example

    import org.apache.commons.io.FileUtils;

import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.regex.Pattern;

public final class SedUtil {

    public static void main(String... args) throws Exception {
        final File file = new File("items.xml");
        final String line = "<bid>\\d+</bid>";
        final String currentBid = "<bid>20</bid>";
        final String data = "<bids><bid>10</bid></bids>";
        FileUtils.write(file, data);
        sed(file, Pattern.compile(line), currentBid);
        System.out.println(data);
        System.out.println(FileUtils.readFileToString(file, StandardCharsets.UTF_8));
    }

    public static void sed(File file, Pattern regex, String value) throws IOException {
        String contents = FileUtils.readFileToString(file, StandardCharsets.UTF_8.name());
        contents = regex.matcher(contents).replaceAll(value);
        FileUtils.write(file, contents);
    }
}

which gives output

<bids><bid>10</bid></bids>
<bids><bid>20</bid></bids>

Upvotes: 0

Cory Koch
Cory Koch

Reputation: 514

You need to make sure the path to the file is correct, java may not have the same path to the file unless it is in the jar. You can do this by trying to open the file or checking if it exists before passing it to the command.

see: How to read file from relative path in Java project? java.io.File cannot find the path specified

Upvotes: 1

L. Quastana
L. Quastana

Reputation: 1336

Try that :)

The advantage of this solution , it's more easier to debugging because you have the temporary file !

String lineIndex="21";
String line="2";
String currentBid="102";

File temp = File.createTempFile("temp-sh", ".sh"); 



FileWriter fw = new FileWriter(temp);
fw.write("#!/bin/bash\n");
fw.write("sed -i '"+lineIndex+"s/"+line+"/"+currentBid+"/g' data/jsp/items.xml\n");
fw.close();
System.out.println(". "+temp.getAbsolutePath());
Runtime.getRuntime().exec(". "+temp.getAbsolutePath());

Upvotes: 1

Elliott Frisch
Elliott Frisch

Reputation: 201477

You should probably use a ProcessBuilder instead of Runtime.exec, perhaps something like this -

try {
  String replaceCommand ="'"+lineIndex+"s/"+line+"/"+currentBid+"/g'";
  String [] cmd = new String[] {
      "sed", "-i", replaceCommand, "/data/jsp/items.xml"  
  };
  Process process = new ProcessBuilder(cmd)
      .start();
  InputStream is = process.getInputStream();
  InputStreamReader isr = new InputStreamReader(is);
  BufferedReader br = new BufferedReader(isr);
  String lineRead;

  System.out.printf("Output of running %s is:",
      Arrays.toString(cmd));

  while ((lineRead = br.readLine()) != null) {
    System.out.println(lineRead);
  }
} catch (IOException e) {
  e.printStackTrace();
}

Upvotes: 1

Related Questions