2013-11-27 145 views
2

我試圖從java運行一個sed命令沒有成功。這是我的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

**編輯

我提出基於以下意見如下變化。然而,輸出沒有變化。

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

好像它會更好,對我來說,到流的XML中Java並執行搜索並以Java替換,而不是從外部shell執行'sed' – Kirby

回答

0

試一下:)

這個解決方案的優點,它更容易調試,因爲你必須臨時文件!

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

我收到一條錯誤消息:線程「main」中的異常java.io.IOException:無法運行程序「。」:java.io.IOException:error = 13,權限被拒絕 – cHam

+0

而不是File.createTempFile,在你有權限的目錄 –

1

你應該使用的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(); 
} 
1

你需要確保的文件路徑是正確的,JAVA可能不會有相同的路徑該文件,除非它在罐子裏。您可以通過在將文件傳遞給命令之前打開文件或檢查它是否存在來做到這一點。

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

+0

我不確定你的意思。文件items.xml永遠不會改變,讀取輸入流如何改變文件? – cHam

+0

對不起,我沒有意識到這個例子中缺少p的類型。 p是您訪問輸出的類型進程,請參閱:http://docs.oracle.com/javase/7/docs/api/java/lang/Process.html –

+0

對不起,我沒有意識到該示例缺少類型頁。 p是通過其getInputStream方法訪問輸出的類型流程。見:HTTP://docs.oracle.com/javase/7/docs/api/java/lang/Process。html –

0

老實說,在這種情況下,沒有必要從外部執行sed。用Java讀取文件並使用Pattern。然後你的代碼可以在任何平臺上運行。將其與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>