【问题标题】:sed command not working from javased命令在java中不起作用
【发布时间】:2013-11-27 02:13:51
【问题描述】:

我正在尝试从 java 运行 sed 命令但没有成功。这是我的java代码:

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

我也试过了:

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

问题是,如果我打印出cmd String 的内容并在终端中运行它,它确实可以工作。由于某种原因,它只是没有从 java 执行它。让这一点更清楚,当我直接从终端运行命令时,文件“items.xml”会发生变化。当我从java运行它时,文件不会改变。我已经验证了该命令是正确的,如下所示。

我错过了什么吗?

cmd 的输出是sed -i '21s/2/102/g' /data/jsp/items.xml

** 编辑

我根据下面的 cmets 进行了以下更改。但是输出没有变化。

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();

【问题讨论】:

  • 对我来说,在 Java 中流式传输 XML 并在 Java 中进行搜索和替换而不是从外部 shell 执行 sed 似乎会更好

标签: java sed


【解决方案1】:

试试看 :)

这个解决方案的优点,因为你有临时文件,调试起来更容易!

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());

【讨论】:

  • 我收到一条错误消息:线程“主”java.io.IOException 中的异常:无法运行程序“。”:java.io.IOException:错误=13,权限被拒绝
  • 代替 File.createTempFile ,在你有权限的目录下创建文件
【解决方案2】:

您可能应该使用ProcessBuilder 而不是Runtime.exec,也许是这样的 -

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();
}

【讨论】:

    【解决方案3】:

    您需要确保文件的路径正确,java 可能没有相同的文件路径,除非它在 ​​jar 中。您可以通过尝试打开文件或在将其传递给命令之前检查它是否存在来做到这一点。

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

    【讨论】:

    • 我不确定你的意思。文件 items.xml 永远不会改变,读取输入流如何使文件改变?
    • 对不起,我没有意识到这个例子缺少 p 的类型。 p 是您访问输出的进程类型,请参阅:docs.oracle.com/javase/7/docs/api/java/lang/Process.html
    • 对不起,我没有意识到这个例子缺少 p 的类型。 p 属于 process 类型,您可以通过其 getInputStream 方法访问输出。见:docs.oracle.com/javase/7/docs/api/java/lang/Process.html
    • 因此 inputStream 用于进程对象而不是您正在运行命令的文件。
    • 我在上面发布了更改。没有帮助。
    【解决方案4】:

    老实说,在这种情况下不需要外部执行sed。用 Java 读取文件并使用Pattern。然后你就有了可以在 any 平台上运行的代码。将其与org.apache.commons.io.FileUtils 结合使用,只需几行代码即可完成。

        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);
    

    或者,在一个简短的、独立的、正确的例子中

        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);
        }
    }
    

    给出输出

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

    【讨论】:

    • 这对于大文件来说并不理想,因为它将整个文件读入内存。
    • 是的。好点子。它可以转换为使用流或缓冲区。
    猜你喜欢
    • 2014-09-16
    • 1970-01-01
    • 2018-11-24
    • 1970-01-01
    • 2017-01-23
    • 2017-03-05
    • 1970-01-01
    • 2016-09-06
    • 2023-03-19
    相关资源
    最近更新 更多