Java 命令字符串中带引号的Groovy外部命令
这是有关的。我在组件列表中加的引号被shell解释为命令本身的一部分 这是应该运行的命令(如果直接在命令行上运行,则不会): 问题似乎来自“test1”和“test2” 这将作为ArrayList传递到命令方法中,然后转换为字符串:Java 命令字符串中带引号的Groovy外部命令,java,groovy,Java,Groovy,这是有关的。我在组件列表中加的引号被shell解释为命令本身的一部分 这是应该运行的命令(如果直接在命令行上运行,则不会): 问题似乎来自“test1”和“test2” 这将作为ArrayList传递到命令方法中,然后转换为字符串: void addComponents(String repository, String name, String flowTarget, ArrayList components) { String compStr = components.toStrin
void addComponents(String repository, String name, String flowTarget, ArrayList components) {
String compStr = components.toString().replace("[", "'").replace("]", "'").replace(", ", "' '")
println compStr
String cmd = "scm workspace add-components ${name} -s ${flowTarget} ${compStr} -r ${repository}"
println cmd
def proc = ["scm", "workspace","add-components", "${name}","-s", "${flowTarget}","${compStr}","-r", "${repository}"].execute()
//def proc = cmd.execute()
proc.waitFor()
getReturnMsg(proc)
}
我尝试了直接字符串以及将命令放入数组并传递给执行
Unmatched component ""test1" "test 2""
从错误中可以看出,它不是在寻找组件test1,而是在一起寻找“test1 test2”
基于此,我似乎需要将“test1”和“test2”分离为数组中的单独元素,如下所示:
def proc = ["scm", "workspace", "add-components","Jenkins_${name}_${workspaceId}_Workspace","-s",flowTarget,"test1","test 2","-r",repository].execute()
事实上,如果我像这样将组件列表硬编码到命令数组中,它确实可以工作
问题在于,组件列表的长度因项目而异。有没有办法像这样构造一个可变长度的命令数组?组件列表来自一个JSON文件,其结构如下:
{
"project": [
{
"name": "Project1",
"components": [
"component1",
"component 2",
"component 3"
]
},
{
"name": "Project2",
"components": [
"component1",
"component 4",
"component 5",
"component6"
]
}
]
}
Groovy的
String#execute()
和Java的Runtime#exec(String)
使用一个简单的新Java.util.StringTokenizer()
来分割参数。没有涉及shell,因此分割规则不同(而且更原始)。传递列表/数组更安全,在这种情况下,拆分是显式的,参数将按原样传递给进程。这意味着您需要确保参数不包含任何不应传递给进程的字符(如引号)。解决方案是将每个组件(存储在单独的列表中)单独添加到命令列表中,而不是作为一个字符串分组:
def components = ["test1", "test 2"]
def cmd = ["scm", "workspace", "flowtarget", "test-workspace", "test-stream", "-r", url, "-C"]
for (component in components) {
cmd.add(component)
}
def proc = cmd.execute()
proc.waitFor()
我想这就是为什么我感到困惑的原因,我在上面所做的传递数组是无效的。如果我打印出数组,它显示为
proc:[scm,workspace,add components,test workspace,-s,teststream,'test1',test2',-r,https://url]
此打印输出确实包含引号(例如,“test1”
),这些引号将被传递。顺便说一句,“${name}”
应该是name
(没有理由在这里使用字符串插值)。好的,这些名称周围应该有引号,但该命令似乎添加了一个额外的集合。我通过在数组中循环并对数组中的每个项运行一次命令来解决这个问题。这不是最好的方法,但至少它是有效的。是的,它将具有空格的组件解释为单个元素-“测试2”变成“测试2”。好的,打印输出表明您将它们作为单个元素传递(否,test1
和test2
)。也许这就是问题所在。
def components = ["test1", "test 2"]
def cmd = ["scm", "workspace", "flowtarget", "test-workspace", "test-stream", "-r", url, "-C"]
for (component in components) {
cmd.add(component)
}
def proc = cmd.execute()
proc.waitFor()