2010-01-19 246 views
3

我有一个在几个平台(特别是Windows,Solaris & AIX)上运行的Java“代理程序”。我想通过在我执行的命令行中使用环境变量来分析文件系统结构中的差异。Java Runtime.exec运行的命令中的环境变量评估()

据我所知,没有办法让Runtime.exec()方法来解析/评估命令String(或String数组)中引用的任何环境变量。

我知道,如果推动推动我可以写一些代码来预处理命令字符串和手动解决环境变量(使用getEnv()等)。不过,我想知道是否有更聪明的方法来做到这一点,因为我确信我不是唯一想做这件事的人,我确信在“敲”我自己的实施方面存在缺陷。

我们非常欢迎您的指导和建议。

编辑: 我想使用一些一致的符号(如$ VAR和/或%VAR%)在命令字符串中引用环境变量。没有融化哪个。

编辑: 要清楚,我想能够执行一个命令,例如:

perl $SCRIPT_ROOT/somePerlScript.pl args

在Windows和UNIX主机使用Runtime.exec()。我在配置文件中指定了描述要运行的作业列表的命令,并且它必须能够跨平台工作,因此我认为环境变量将有助于分析文件系统差异(/home/username/scripts vs C:\foo\scripts)。希望有助于澄清它。

谢谢。 Tom

+0

你是如何解决这些问题的?在传递给'Runtime.exec()'的命令字符串中使用'$ VAR'的Unix shell方法? – 2010-01-19 02:40:53

+0

@凯文 - 是的。理想的情况下。 – 2010-01-19 02:51:34

回答

6

我想我误解了你的问题和我的原始答案。如果您正尝试解析您在Java中使用生成的命令行上的环境变量引用,我认为您可能需要“自行开发”。

根据操作系统的不同,这些扩展方式有很多不同的标准。另外,这通常是shell的一个功能,所以即使在同一个操作系统上也可能有不同的方式。事实上,标准的操作系统进程激活功能(例如Unix中的exec)不会执行命令行扩展。

这对于Java 5及更高版本来说并不难。为自己定义一个标准,我通常使用您在安全策略文件中看到的Java标准和一些增强的属性文件定义 - ${var}扩展为变量/属性名称引用。喜欢的东西:

private static String expandCommandLine(final String cmd) { 
     final Pattern vars = Pattern.compile("[$]\\{(\\S+)\\}"); 
     final Matcher m = vars.matcher(cmd); 

     final StringBuffer sb = new StringBuffer(cmd.length()); 
     int lastMatchEnd = 0; 
     while (m.find()) { 
      sb.append(cmd.substring(lastMatchEnd, m.start())); 
      final String envVar = m.group(1); 
      final String envVal = System.getenv(envVar); 
      if (envVal == null) 
       sb.append(cmd.substring(m.start(), m.end())); 
      else 
       sb.append(envVal); 
      lastMatchEnd = m.end(); 
     } 
     sb.append(cmd.substring(lastMatchEnd)); 

     return sb.toString(); 
    } 
+0

干杯 - 我怀疑这将是我最终做的事情。我确信我不是第一个尝试它的人。也许我使用错误的术语来搜索。也感谢代码。 – 2010-01-19 09:28:58

+0

我会用'sb.append(cmd,lastMatchEnd,m.start())'替换'sb.append(cmd.substring(lastMatchEnd,m.start()))'以避免字符串复制。与另外两次调用'sb.append(... substring(...))'类似。 – 2016-03-04 06:53:03

1

是否有某些原因系统属性不起作用?在命令行上使用-D标志,然后你可以通过System.getProperty来检索它

+0

嘿史蒂夫 - 我不知道这将如何帮助?也许我的问题不清楚。我会尽力澄清它。 – 2010-01-19 02:53:20

0

只是因为我在我的剪贴板(由你真正编码),它在一个字符串工作Windows环境变量分辨率代码,我只是将它张贴在这里了。这也许是最有效的方法(也许正则表达式效率低得多,我不确定)。

int from  = 0; 
int startperc = -1; 
int endperc = -1; 

while (true) { 
    int index = tok.indexOf("%", from); 
    if (index == -1) break; 
    if (startperc == -1) { 
     startperc = index; 
    } else if (endperc == -1) { 
     endperc = index; 
    } 
    from = index + 1; 

    if (startperc >= 0 && endperc > startperc) { 
     String startbit = tok.substring(0, startperc); 
     String middlebit = System.getenv(tok.substring(startperc + 1, endperc)); 
     String endbit = endperc <= tok.length() ? tok.substring(endperc + 1) : ""; // substr up to end 

     // integrate 
     tok = startbit + middlebit + endbit; 

     // reset 
     startperc = -1; 
     endperc = -1; 
    } 
} 
1

正则表达式

[$]\\{(\\S+)\\} 

是贪婪(S+)和在xx ${a} xx ${b} xx情况下它将匹配A} xx ${B代替seperately AB。你有没有在cmd中用多个变量测试它?

所以如果有多个变量需要替换。它应该是

[$]\\{(\\S+?)\\}