执行shell脚本从Java一个空的参数 [英] Executing a shell script with an empty argument from Java

查看:193
本文介绍了执行shell脚本从Java一个空的参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的bash脚本,需要在几个参数的测试,然后和运行一个命令如下图所示。

I have bash script that takes in a couple of arguments tests then and runs a command as shown below

call script => /bin/bash myscript arg1 arg2 arg3 arg4
comm called => command -a arg1 -b arg2 -c arg3 -d arg4

如果一个参数为空,则该选项不叫。

if a parameter is empty then that option is not called.

call script => /bin/bash myscript arg1 arg2 '' arg4
comm called => command -a arg1 -b arg2 -d arg4

我可以用下面一行的脚本来测试的参数来实现这个

I am able to achieve this by using following line in the script to test the arguments

if test "${arg3:-t}" != "t" ; then

这提示调用时这个脚本就像一个魅力。即使我有,替换为它工作正常空的参数。

This script works like a charm when called from prompt. even if I replace '' with "" for an empty argument it works fine.

这时候开始使用我exec调用该脚本从Java失败。

This starts failing when I call this script from java using exec.

Process p = Runtime.getRuntime().exec("/bin/bash myscript arg1 arg2 '' arg4");
expected command => command -a arg1 -b arg2 -d arg4 (as in above example)
actual command   => command -a arg1 -b arg2 -c '' -d arg4

我不能够理解为什么这会发生。哪里有问题?在shell脚本或方式,命令从Java执行的?

I am not able to understand why this would be happening. Where is the problem? In the shell script or in the way it command is executed from java?

这怎么能解决吗?

推荐答案

基本的问题是Java根本不花哨做任何事情来解析你给它的字符串,并很好地分解成参数。

The basic problem is that java doesn't do anything at all fancy to parse the string you give it and break it nicely into arguments.

简短的回答是使用的Runtime.exec 的String [] 版本:

The short answer is to use the String [] version of Runtime.exec:

Runtime.getRuntime().exec(
    new String[] {"/bin/bash", "myscript", "arg1", "arg2", "",  "arg4"});

如果您有其他地方的参数解析比这更令人费解的,你可以把这个字符串的解析了抨击,并做到:

If you have other places where the argument parsing is more convoluted than that, you can pass the parsing of the string off to bash, and do:

Runtime.getRuntime().exec(
    new String[] {"/bin/bash", "-c", "/bin/bash myscript arg1 arg2 '' arg4"});

如果你正在转换的东西比那在做复杂的重定向一个巨大的数字,如 2 - ;&放大器; 1 或建立整个管道,则可能需要这个的bash -c 欺骗。

If you're converting something over that's doing a huge number of complicated redirects like 2>&1 or setting up a whole pipeline, you might need this bash -c trick.

编辑:

要明白是怎么回事,你必须意识到,当用户空间code告诉内核加载此可执行这些论点,并基于该启动一个进程(*),什么是传递到内核是一个可执行文件,字符串为参数数组(该参数数组的第0 /第一个元素是可执行文件,做一些奇怪的时除外的名称),字符串对环境的数组。

To understand what's going on here, you have to realize that when user-space code tells the kernel "load this executable with these arguments and start a process based on that" (*), what's passed on to the kernel is an executable, an array of strings for arguments (the 0th/first element of this argument array is the name of the executable, except when doing something weird), and an array of strings for the environment.

什么bash所做的,当它看到这一行:

What bash does when it sees this line:

/bin/bash myscript arg1 arg2 '' arg4

是想好吧, /斌/庆典不是一个内置的,所以我的东西执行,让我们用我的串放在一起的参数数组的子进程解析算法,了解行情和诸如此类的东西。巴什然后确定参数传递给内核的新工艺有:

is think "Okay, /bin/bash isn't a builtin, so I'm executing something. Let's put together the argument array for the subprocess using my string parsing algorithms, which know about quotes and whatnot". Bash then determines that the arguments to pass the kernel for the new process are:


  • /斌/庆典

的MyScript

ARG1

ARG2

(空字符串)

ARG4

现在bash有它适用于这里pretty复杂的字符串处理算法 - 它接受两种不同的报价,它会做 $ VAR的扩张时,外面发生的字符串或双引号中,它会在反引号与输出替换子等。

Now bash has pretty complicated string processing algorithms that it applies here - it accepts two different kinds of quotes, it'll do expansion of $VAR when it happens outside strings or inside double quotes, it'll replace subcommands in backquotes with the output, etc.

当你调用 EXEC 的单串的Java版本并没有做任何事情,那么老练。它只是创建了一个新的的StringTokenizer 并使用该分手,你给它进入的参数的字符串。这个类不知道什么行情;它拆分该字符串成:

Java doesn't do anything so sophisticated when you call the single string version of exec. It just creates a new StringTokenizer and uses that to break up the string you give it into arguments. That class doesn't know anything about quotes; it splits that string up into:


  • /斌/庆典

的MyScript

ARG1

ARG2

(有两个字符,这两者都是单引号字符串)

'' (a string with two characters, both of which are the single quote)

ARG4

Java的然后调用的 EXEC 的String [] 版本。 (当然,其中之一)

Java then calls the String[] version of exec. (Well, one of them)

人们采摘尼特这一注:

(*)是的,我特意eliding系统调用之间的差异的execve 。 pretend他们是一个电话的那一刻。

(*) Yes, I'm deliberately eliding the difference between the system calls fork and execve. Pretend they're one call for the moment.

这篇关于执行shell脚本从Java一个空的参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆