(注意:我已经看过类似的问题(例如this,问题是无法修剪shell命令的输出),但我认为这种情况是不同的。)
我在Groovy中有一个使用参数(通过properties([parameters([...
)的管道脚本。当我将参数的值插值到双引号引起来的字符串中时,它无法针对捕获到的两个对象(我的意思是“捕获的和.trim()d!!”)进行.equals()
检查(这是我的用例),甚至是一个简单的字符串文字。
我可以使用.trim()
来解决该问题(尽管您可以通过回显它们并检查.length()
来查看.trim()
的内容,但是您可以看到),但是我怀疑只有“有效”,因为它会执行隐式.toString()
,这也是一种成功的解决方法。
对我来说,这似乎是个错误,但这实际上是我与Groovy合作的第一周,所以也许我错过了一些东西-有人可以解释什么吗?
即使简单的文字"foo"
也会失败(即"foo".equals("${params.foo_the_parameter}"
)。插值参数是其他种类的对象还是其他东西?
[ EDIT ”从@Matias Bjarland获得答案后,我修改了下面的代码以使用println而不是带壳的echo,因为它使输出更加简洁。他建议的解决方案将显示在带注释的方框中。]
我的常规代码:
node() {
properties([
parameters([
string(
defaultValue: 'foo',
description: 'This is foo',
name: 'foo_the_parameter'
)
])
])
/* this is what I learned from the accepted answer
bob="${params.foo_the_parameter}"
println("class of interpolated param is ${bob.class}")
simple_foo="foo"
println("class of \"foo\" is ${simple_foo.class}")
*/
echoed_foo = sh(script:"echo 'foo'", returnStdout: true).trim()
println "echoed foo is [$echoed_foo], params foo is [${params.foo_the_parameter}]";
echo_foo_length = echoed_foo.length()
dqs_foo_length = "${params.foo_the_parameter}".length()
println "their lengths are: echo: [$echo_foo_length] and dqs: [$dqs_foo_length]";
if (echoed_foo.equals("${params.foo_the_parameter}")) {
println "SUCCESS they are equals()"
}
else {
println "FAIL they are not equals()" //this one fires
}
if (echoed_foo.equals("${params.foo_the_parameter}".trim())) {
println "SUCCESS they are equals() after the dqs gets a trim()" //this one fires
}
else {
println "FAIL they are not equals()after the dqs gets a trim()"
}
if (echoed_foo.equals("${params.foo_the_parameter}".toString())) {
println "SUCCESS they are equals() after the dqs gets a toString()" //this one fires
}
else {
println "FAIL they are not equals()after the dqs gets a toString()"
}
if ("foo".equals("${params.foo_the_parameter}")) {
println "SUCCESS at least a simple literal \"foo\" works"
}
else {
println "FAIL even a simple literal \"foo\" fails to be .equals() with the interpolated parameter" //this one fires
}
}
詹金斯的输出:
Started by user Michael South
[Office365connector] No webhooks to notify
Obtained jenkins.groovy from git git@github.redacted.com:msouth/test_groovy_equals.git
Running in Durability level: MAX_SURVIVABILITY
[Pipeline] node
Running on subnet_mon_02 in /opt/jenkins/m1/workspace/field-analytics-org/test_string_equals
[Pipeline] {
[Pipeline] properties
[Pipeline] sh
[test_string_equals] Running shell script
+ echo foo
[Pipeline] echo
echoed foo is [foo], params foo is [foo]
[Pipeline] echo
their lengths are: echo: [3] and dqs: [3]
[Pipeline] echo
FAIL they are not equals()
[Pipeline] echo
SUCCESS they are equals() after the dqs gets a trim()
[Pipeline] echo
SUCCESS they are equals() after the dqs gets a toString()
[Pipeline] echo
FAIL even a simple literal "foo" fails to be .equals() with the interpolated parameter
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
[Office365connector] No webhooks to notify
Finished: SUCCESS
答案 0 :(得分:2)
==
来比较字符串在Java中,您使用String.equals()
是因为str1 == str2
并没有达到您的期望:Java比较引用而不是值。
在Groovy中,您只需编写str1 == str2
,它便可以完成您期望的工作。 Groovy使用String.compareTo()
比较值,并在结果为true
时返回0
。
GString g = "${'foo'}"
String s = "foo"
assert g == "foo" && s == "foo"
assert g instanceof GString && s instanceof String
assert !s.equals(g) && !g.equals(s)
assert g.compareTo(s) == 0 && s.compareTo(g) == 0
assert g == s && s == g
答案 1 :(得分:1)
不确定这是否是您要的内容,但请考虑以下常规代码:
def x = 'World'
def gstr = "Hello ${x}!"
def str = 'Hello World!'
println "class of gstr: ${gstr.class}"
println "class of str: ${str.class}"
println(gstr.equals(str))
println(gstr.toString().equals(str))
运行时会打印:
~> groovy solution.groovy
class of gstr: class org.codehaus.groovy.runtime.GStringImpl
class of str: class java.lang.String
false
true
~>
换句话说,字符串内插将导致groovy GString的实例,该实例不一定等于具有相同内容的字符串。使用.toString()
强制评估可以解决此特定问题。
引用groovy documentation on string interpolation:
任何Groovy表达式都可以插入所有字符串文字中,除了单引号和三重单引号字符串之外。插值是在评估字符串时用其值替换字符串中占位符的行为。占位符表达式用$ {}包围,或者对于点缀表达式用$前缀。当GString传递给通过对表达式调用toString()以String为参数的方法时,占位符内部的表达式值将按其字符串表示形式求值。
换句话说,您必须使用以下一些变体将GString实例分配给计划java字符串:
String str1 = gstr
def str2 = gstr as String
def str3 = (String) gstr
,调用采用字符串(将GString强制转换为字符串)的方法,或调用gstr.toString()
强制转换。
希望有帮助。