简体   繁体   English

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

[英]How can I correctly escape string for awk input using Java?

I'm trying to execute the following command (which works on the terminal) within Java: 我正在尝试在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

The Java code I am using is this: 我正在使用的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);

The error I am getting is: 我得到的错误是:

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

Any ideas of what am I doing wrong? 我有什么不对的想法吗?

When you use Runtime.getRuntime().exec(command) , it takes the string and breaks it into a command and arguments based on spaces. 当您使用Runtime.getRuntime().exec(command) ,它接受字符串并将其分解为基于空格的命令和参数。

This simple parsing is not the same as the parsing done by the shell when you invoke the command. 这种简单的解析与调用命令时shell执行的解析不同。 The shell, for example, takes quotes into consideration. 例如,shell考虑了引号。 This means that if you have a command line like: 这意味着如果你有一个命令行,如:

cmd 'abc' 'def'

The arguments that the shell will send to the cmd command are going to be abc and def . shell将发送到cmd命令的参数将是abcdef But if you give the same command to Runtime.getRuntime().exec(command) , it will send 'abc' and 'def' to cmd as arguments. 但是如果你给Runtime.getRuntime().exec(command)提供相同的命令,它会将'abc''def'作为参数发送给cmd Yes, including the quotes! 是的, 包括报价!

The situation gets worse if you have spaces in any of the arguments. 如果在任何参数中都有空格,情况会变得更糟。 If the shell gets 如果shell得到了

cmd 'my single argument'

It will invoke the command with a single argument my single argument . 它会调用带一个参数的命令, my single argument But Runtime.getRuntime().exec(command) will invoke cmd with three arguments: 'my , single and argument' ! Runtime.getRuntime().exec(command)将使用三个参数调用cmd'mysingleargument'

So it's not recommended to use this particular overload for anything but very simple commands. 因此,除了非常简单的命令之外,不建议将此特定重载用于任何操作。 Instead, you should use the overload that accepts an array of strings. 相反,您应该使用接受字符串数组的重载。 The first element should be the command name, and each argument should be in a separate element: 第一个元素应该是命令名,每个参数应该在一个单独的元素中:

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

Note: It is recommended to use the ProcessBuilder class to build a Process rather than Runtime.getRuntime.exec - it gives you better control of the command and you can pass the separate arguments right to the constructor. 注意:建议使用ProcessBuilder类来构建Process而不是Runtime.getRuntime.exec - 它可以让您更好地控制命令,并且可以将单独的参数传递给构造函数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM