如何使用Java正确转义字符串以进行awk输入?

时间:2015-10-28 13:05:07

标签: java string unix awk

我试图在Java中执行以下命令(适用于终端):

awk -F';' 'NR>1{gsub(/; +/,";",$0);printf("{msisdn:\"%s\",imei:\"%s\",brand:\"%s\",model:\"%s\",sap:\"%s\",sap_cod:\"%s\",file_name:\"teste\",company:{\"$ref\":\"company\",\"$id\":ObjectId\"456\")}}\n",$2,$15,$16,$17,$18,$20)}' /Users/milena/Desktop/giant.csv

我正在使用的Java代码是:

String fileName = "test";
String company = "456";

String awk = "awk -F';' 'NR>1";
String gsub = "{gsub(/; +/,\";\",$0);";

String printf = "printf(\"{msisdn:\\\"%s\\\",imei:\\\"%s\\\",brand:\\\"%s\\\","
            + "model:\\\"%s\\\",sap:\\\"%s\\\",sap_cod:\\\"%s\\\",file_name:\\\""+fileName+"\\\",company:"
            + "{\\\"$ref\\\":\\\"company\\\",\\\"$id\\\":ObjectId\\\""+company+"\\\")}}\\n\",$2,$15,$16,$17,$18,$20)}\' ";

String path = "/Users/milena/Desktop/giant.csv";

String command = awk + gsub + printf  + path; 

Process p
p = Runtime.getRuntime().exec(command);

我得到的错误是:

awk: syntax error at source line 1
    context is
     >>> ' <<< 
    missing }
    missing )
awk: bailing out at source line 1

关于我做错什么的任何想法?

1 个答案:

答案 0 :(得分:3)

当你使用Runtime.getRuntime().exec(command)时,它接受字符串并将其分解为基于空格的命令和参数。

这种简单的解析与调用命令时shell执行的解析不同。例如,shell考虑了引号。这意味着如果您有一个命令行,如:

cmd 'abc' 'def'

shell将发送到cmd命令的参数将是abcdef。但是,如果您向Runtime.getRuntime().exec(command)提供相同的命令,它会将'abc''def'作为参数发送给cmd。是的,包括引号!

如果任何参数中有空格,情况会变得更糟。如果shell得到

cmd 'my single argument'

它将使用单个参数my single argument调用该命令。但Runtime.getRuntime().exec(command)会使用三个参数调用cmd'mysingleargument'

因此,除了非常简单的命令之外,不建议将此特定重载用于任何操作。相反,您应该使用接受字符串数组的重载。第一个元素应该是命令名,每个参数应该在一个单独的元素中:

String[] command = { "awk",
                     "-F;",
                     "NR>1{gsub(/; +/,\";\",$0);printf(\"{msisdn:\\\"%s\\\",...",
                     "/Users/milena/Desktop/giant.csv"
                   };
Process p = Runtime.getRuntime().exec(command);

注意:建议使用ProcessBuilder类来构建Process而不是Runtime.getRuntime.exec - 它可以让您更好地控制命令,并且可以将单独的参数传递给构造函数。