如何在Jenkinsfile中获取Shell脚本输出并提取指定列值?
这个问题很常见——Jenkins Pipeline里的shell步骤是在独立进程里运行的,shell内部的变量没法直接传递到Groovy层面使用。我给你几个靠谱的解决办法,一步步来:
首先,你原来的写法有两个核心问题:
- 使用了
returnStatus: true,这个参数返回的是shell命令的退出码(0表示成功,非0表示失败),而非命令的输出内容; - shell里定义的
COLS变量只在当前shell进程的生命周期内有效,Groovy完全访问不到它。
正确的思路是把shell命令的输出捕获到Groovy变量中,然后在Groovy层面处理或直接使用。这里有两种常用的实现方式:
方法一:用awk直接提取目标列(最简洁可靠)
ls的输出列之间可能存在多个空格,用awk处理比手动分割字符串靠谱得多——它会自动把任意数量的空白符当成分隔符。我们可以直接让shell输出需要的第五列,再让Groovy捕获这个值:
stage("Get dir size") { steps { script { // 执行命令并捕获第五列输出,trim去掉多余的换行和空格 def dirSize = sh( returnStdout: true, script: '''ls -al | grep "^d.*some_dir" | awk '{print $5}' ''' ).trim() // 现在你可以自由使用这个变量了! echo "some_dir的大小是:${dirSize} 字节" // 示例:做数值判断 if (dirSize.isInteger()) { def sizeInKB = dirSize.toInteger() / 1024 echo "换算成KB是:${sizeInKB} KB" } } } }
这里grep "^d.*some_dir"是为了确保只匹配目录(^d表示行首是d,对应ls里的目录权限位),避免匹配到文件名带some_dir的普通文件。如果确定目标目录唯一,也可以简化成ls -al some_dir | awk '{print $5}',无需grep。
方法二:Groovy层面分割输出(适合复杂场景)
如果你需要对ls的整行输出做更多处理(比如同时提取所有者、组等信息),可以先把整行输出拿到Groovy,再用Groovy的字符串分割方法处理:
stage("Get dir size") { steps { script { // 先拿到匹配行的完整输出 def dirLine = sh( returnStdout: true, script: '''ls -al | grep "^d.*some_dir" ''' ).trim() // Groovy里用正则分割任意空白符,得到列数组 def cols = dirLine.split(/\s+/) // 第五列对应数组索引4(数组从0开始计数) def dirSize = cols[4] echo "提取到的目录大小:${dirSize}" } } }
这种方式适合需要同时提取多列数据的场景。
额外注意事项
- 务必使用
returnStdout: true而非returnStatus: true,前者返回命令的标准输出,后者返回退出码; - 记得用
.trim()处理输出,避免多余的换行符或首尾空格影响后续逻辑; - 如果你的需求是获取目录内容的总大小而非目录本身的大小,建议用
du -s some_dir | awk '{print $1}'代替ls,因为ls输出的只是目录条目本身的大小,而非目录下所有文件的总大小。
内容的提问来源于stack exchange,提问作者Chris F
相关产品推荐
相关产品推荐

