语法
变量
Bpipe支持在脚本中使用变量。在Bpipe中有两种变量:
- 隐式变量:Bpipe默认为您定义的变量
- 显式变量:自己定义的变量
隐式变量
隐式变量是自动提供给Bpipe阶段的特殊变量。两个重要的隐式变量是:
- input:定义传递给阶段的输入文件的名称
- output:定义从阶段输出的文件的名称
- branch:当流程运行并行分支任务时,当前分支的名称可用
$branch
变量替代。 - threads:一个特殊的变量,它使Bpipe对任务自动估计并分配适当数量的线程
- memory:一个特殊的变量,它接受
bpipe.config
中分配的内存值。如果被引用,还会使Bpipe遏制为流程设置的资源限制(例如:使用Bpipe run -m)。
Bpipe是根据输入和输出变量,自动地将多个任务连接起来,形成一个流程。一个阶段的默认输入是前一个阶段的输出。通常,您应该始终使用这些变量,而不是将文件名硬编码到命令中。使用这些变量可以确保您的阶段可重复使用,并且可以灵活地连接在一起形成不同的流程。
输入和输出变量的扩展名语法
Bpipe提供了一种特殊的语法,可以方便地引用特定文件类型的输入和输出。
变量的扩展语法
当您使用$input
和$output
变量当作输入和输出文件名时,它将默认为您提供与阶段名称相对应的命名。然而,这种文件扩展名不太好看,并且也可能不是很健壮,因为没有指定要使用的文件类型。例如,$input
将引用前一个阶段的第一个输出。但是如果该阶段有多个输出并且改变了它们的顺序呢?您的阶段将获得错误的文件。为了解决这个问题,您可以为输入和输出变量添加文件扩展名:
align_reads = {
exec "bowtie –S reference $input.fastq | samtools view -bSu - > $output.bam"
}
这里我们指定了这个阶段需要一个文件扩展名为“.fastq”的输入,并将输出一个文件扩展名为“.bam”的文件。第一个将导致 Bpipe 搜索先前阶段的输出以找到.fastq
结尾的文件作为输入。第二个将确保此阶段的输出文件以“.bam”文件扩展名结尾。使用这些文件扩展名是可选的,但它会使您的流程更加健壮。
多个输入的过滤
当阶段接收到多个不同类型的输入时,您可以使用带有扩展名的$inputs
变量来找到那些具有相应的扩展名的输入文件。
例如,要将所有以“.bam”结尾的输入传递给“merge_bam”命令:
merge_bams = {
exec "merge_bams.sh $inputs.bam"
}
限制
目前扩展名语法仅适用于过滤单个扩展名。因此你不能要求$input.fastq.gz
,这会导致错误。对于这些情况,您可以考虑使用from
语句来匹配正确的输入:
align_reads = {
from("fastq.gz") {
exec "bowtie –S reference $input.gz | samtools view -bSu - > $output.bam"
}
}
在这里,我们可以确定我们只会匹配 bowtie 命令中以“.fastq.gz”结尾的文件。
多个输入文件
不同的任务有不同数量的输入和输出文件,所以当一个具有多个输出的阶段连接到一个只有一个输入的阶段时会发生什么? Bpipe的目的是无论您将什么阶段连接在一起,都要努力使程序正常运行。我们通过下面变量引用做到这一点:
- 变量
input1
是指第一个文件名,使得任务可以从本地读取输入文件。如果前一阶段有多个输出,则input1
变量是这些输出中的第一个。此输出被视为“主”或“默认”输出。默认情况下,变量$input
是指input1
的值。 - 如果一个任务想接受多个输入,那么它可以使用
input1
、input2
等变量引用每个输入。 - 如果一个任务有未知数量的输入,它可以将变量输入引用为列表,并使用数组一样的索引来访问元素,例如
input[0]
与input1
相同,input[1]
对应于input2
,等等。您可以使用input.size()
引用输入文件的数量,并使用下面类似的语法对输入文件进行迭代:
for(i in inputs) {
exec "... some command that reads $i ..."
}
- 当一个阶段有多个输出时,第一个这样的输出被视为“主”输出,并作为“输入”变量传递给下一个阶段。如果下一阶段只接受一个输入,那么它的输入将是前一个阶段的主要输出。
- 使用扩展名将过滤输入文件类型,使其只包含特定类型的输入。例如
inputs.bam
将找到所有扩展名为′.bam′的文件,input1.bam
将在上游阶段找到第一个后缀为bam的文件。
显式变量
显式变量是您自己定义的变量。这些变量是使用类似java(或Groovy)的语法在Bpipe脚本中内部创建的。可以在任务内部或任务外部定义它们,以便在任务之间共享它们。例如,这里定义了两个变量,并在两个任务之间共享:
NUMTHREADS=8
REFERENCE_GENOME="/data/hg19/hg19.fa"
align_reads = {
exec "bwa aln -t $NUMTHREADS $REFERENCE_GENOME $input"
}
call_variants = {
exec "samtools mpileup -uf $REFERENCE_GENOME $input > $output"
}
- 注意1 : 必须要知道以这种方式定义的变量具有全局作用域,并且可以修改。如果您的流程有并行的阶段,那么这一点就变得非常重要。因此,对这些变量的修改可能导致任务间冲突、死锁和所有通常出现在多线程编程中的相关问题。出于这个原因,强烈建议您将此类变量视为常量,并只将其赋值一次,然后在脚本的其余部分中将其引用为只读变量,不进行任何修改。
- 注意2 : 显式变量可以在您自己的阶段中进行设置。但是在阶段内定义一个变量,它不是指该阶段的私有变量(即作用域只在该阶段),而是被分配给全局环境。如果您希望定义一个阶段内的私有变量,请在它前面加上
def
。如果你想和其他阶段共享这个变量,你可以用branch
前缀。不限制于分支阶段,所有在这个阶段后面的阶段都可以引用。
align_reads = {
num_threads=8 // bad idea, this is a global variable!
def thread_num=8 // good idea, this is private
branch.thread_num = 8 // good idea if you want the variable to be visible
// to other stages in the same branch
exec "bwa aln -t $num_threads $REFERENCE_GENOME $input"
}
变量取值
大多数情况下,变量会在exec
语句中定义的shell命令中被引用。这些语句使用单引号、双引号或三引号定义命令。每种引号对变量展开的处理略有不同。
双引号会导致变量在传递到shell之前被展开。如果输入文件是"myfile.txt”,语句: exec "echo $input"
的结果等同于下面shell命令:echo myfile.txt
由于shell没看到myfile周围有引号,如果您的文件名包含空格或shell特殊处理的其他字符,此操作将失败。要处理这个问题,可以在文件名周围嵌入单引号: exec "echo '$input'"
。
单引号中的变量传递到shell并不会进行取值。因此exec 'echo '$input'
等同于shell命令:echo $input
三引号很有用,因为它们接受换行符。这允许您格式化跨多行的长命令,而无需费力地转义换行符。三引号以双引号相同的方式转义变量,但是它允许您在传递到shell的命令中嵌入双引号。因此,解决上述空格问题的另一种方法是将语句写成:
exec """
echo "$input"
"""
这等同于shell里的:echo "myfile.txt"
直接引用变量
在任务内部,可以使用类似java(实际上是Groovy)的语法引用变量。在这个例子中,Java代码用于检查输入是否已经存在:
mytask = {
// Groovy / Java code!
if(new File(input).exists()) {
println("File $input already exists!")
}
}
您通常不需要在Bpipe脚本中使用这种语法,但是如果您需要它来处理复杂或高级的场景,那么它是可用的。
与Bash变量的区别
Bpipe 的变量相关语法基本上与Bash和Perl等语言中的语法兼容。这非常方便,因为这意味着您可以直接从命令行复制和粘贴命令到Bpipe脚本中,即使它们使用了环境变量。
但是Bpipe变量语法和Bash变量语法之间有一些小的区别:
- Bpipe总是希望符号后面跟着一个变量名。因此,Bash中使用
$
进行其他操作时需要转义$,这样Bpipe就不会解释它。例如:
exec "for i in $(ls ∗∗.bam); do samtools index $i; done"
在本例中,$后面加上左括号是非法的,因为Bpipe将尝试将其解释为一个变量。我们可以用反斜杠来解决这个问题:
exec "for i in \$(ls **.bam); do samtools index $i; done"
- Bpipe把
.
作为查询属性的特殊字符,而Bash仅用它分隔变量名。因此,如果您希望用$foo.txt
表示一个带有.txt后缀的文件,需要使用大括号${foo}.txt。
环境变量
如果引用一个没有预先定义的变量,变量前面加上符号$
,Bpipe不会进行取值计算。也就是说,在exec命令中,如果未定义,$USER
将被认为是$USER
本身。这使得变量在bash命令中作为环境变量进行传递。例如:
exec """
echo $USER
"""
即使USER
没有被定义,这也将打印环境变量中用户变量的值。注意,Bpipe根本不对这样一个变量进行取值,执行命令时,bash才会根据bash的环境变量进行取值。因此,如果使用计算集群或类似的方法运行命令,则必须为在执行命令的节点上定义环境变量。
并行运行任务
生物信息学流程中经常需要同时执行多个任务。有两种主要的情况下你想要这样做:
- 在同一数据上同时执行多个阶段任务。即你有一组数据,需要同时进行几项独立操作。
- 在不同数据上同时执行多个阶段。即您的数据由许多单独的文件组成,这些文件可以经过部分或全部流程分开处理。
在这两种情况下,您都可以通过并行而不是顺序执行操作来节省大量时间。Bpipe通过一个简单的语法支持这种并行执行,它可以帮助您声明管道的哪些部分可以同时执行,以及应该向它们输入什么。
在同一数据上同时执行多个阶段任务
# 1. 准备输入文件
echo Bpipe > test.txt
# 2. 准备bpipe 流程文件,并命名并helloworld.pipe
hello = {
exec "echo Hello | cat $input.txt - > $output.txt"
}
world = {
exec "echo World | cat $input.txt - > $output.txt"
}
mars = {
exec "echo mars| cat $input.txt - > $output.txt"
}
red = {
exec "echo red | cat $input.txt - > $output.txt"
}
blue = {
exec "echo blue | cat $input.txt - > $output.txt"
}
nice_to_see_you = {
exec "echo 'nice to see you' | cat $input.txt - > $output.txt"
}
nice_to_see_you_all = {
exec "echo 'nice to see you' | cat $inputs.txt - > $output.txt"
}
//run { hello + world } //测试输入输出文件
//run {hello + [world,mars]} //
# 3. 运行测试
bpipe run helloworld.pipe test.txt
现在您有一个非常简单的“hello world”流程,如下所示:
run {hello + world}
这时test.txt作为hello的输入文件被传入,test.hello.txt是输出文件,同时作为world的输入文件。world阶段得到test.hello.world.txt作为输出文件。
现在假设您想添加第二个“mars”阶段,它将与“world”管道阶段同时执行。你所需要做的就是把所有的阶段一起执行在方括号里,用逗号隔开:
run {hello + [ world,mars ]}
注意 : 如果您熟悉Groovy语法,您将注意到方括号表示法是Groovy中定义列表的方式。因此,我们要说的是,如果您给Bpipe一个要处理的阶段列表,它将并行地执行它们。
这时首先执行hello阶段,得到test.hello.txt文件,同时作为world和mars的输入文件。这两个阶段会并行运行,分别得到test.hello.world.txt 和test.hello.mars.txt 文件。
你也可以并行执行多个阶段:
run { hello + [ blue + world, red + mars ]}
这里“blue + world”和“red + mars”形成了并行执行的子管道。首先得到test.hello.txt文件作为blue和red输入文件,并行执行blue和red阶段,分别得到test.hello.blue.txt和test.hello.red.txt文件。它们接着分别作为world和mars的输入文件,并行执行,分别得到test.hello.blue.world.txt和test.hello.red.mars.txt文件
在并行执行完阶段后,也许希望合并输出传入其它阶段:
run {hello + [ world, mars ] + nice_to_see_you}
注意,在本例中,最后一个阶段nice_to_see_you要等到前面所有并行执行的阶段都完成后才会执行。它将接收来自“ world”和“mars”阶段的所有输出组合作为输入。
但是如果nice_to_see_you阶段没有接收多个输入文件,则只会把第一个输出test.hello.world.txt传给nice_to_see_you阶段,得到test.hello.world.nice_to_see_you.txt 。如果想合并world和mars的输出文件,则input变量得改成inputs变量:
run {hello + [world,mars]+ nice_to_see_you_all}
在并行执行阶段后,把它们合并起来,最后可能还想并行其它阶段。即在hello + [world,mars]后,同时合并前面输出,且对[world,mars]的结果分别执行并行welcome,最后得到test.hello.world.nice_to_see_you_all.txt, test.hello.world.welcome.txt和test.hello.mars.welcome.txt。但是下面的代码并不会得到这三个结果文件:
run {hello + [world,mars]+ [nice_to_see_you_all+welcome] }
因为[world,mars]的输出有两个,传入welcome后不会并行处理,而是只会处理第一个输出文件,即test.hello.world.txt。 这时你需要嵌套并行任务:
run {hello + [world,mars]+ [nice_to_see_you_all,"test.hello.%.txt"*[welcome]] }
在这种情况下,world和mars阶段将同时执行,完成后的两个输出文件才会被传入下一个阶段,即nice_to_see_you_all和welcome。而nice_to_see_you_all会合并所有结果,welcome又进入并行阶段,把上一阶段的两个输出当作输入并行执行,最张得到想要的test.hello.world.nice_to_see_you_all.txt, test.hello.world.welcome.txt和test.hello.mars.welcome.txt三个文件。
基于染色体的并行化
在生物信息学中,常常需要多条染色体同时进行操作。Bpipe使用下面的特殊语法使这一点很容易实现:
Bpipe.run {
chr(1..5) * [ hello ]
}
这将并行运行5个“hello”阶段的实例,每个实例接收相同的文件作为输入。每个阶段都将接收一个隐式chr
变量,该变量可用于引用该阶段将要处理的染色体。这可以用于许多以染色体号为参数的软件,来指定要处理的特定区域。例如,使用samtools:
hello = {
exec """samtools view test.bam $chr | some_other_tool """
}
可以指定多个范围或单个染色体:
Bpipe.run {
chr(1..10, 'X','Y') * [ hello ]
}
这将并行运行12个hello阶段的实例,每个hello阶段实例会授受隐式chr变量,在不同实例中其值为“chr1”到“chr10”、“chrX”和“chrY”。
注意:Bpipe还提供了$region
变量。如果没有声明基因组,Bpipe将为流程内的语句指定如下形式的区域:chrN:0-0
。许多软件认为这种区域是指整个染色体。但是,如果您声明了一个基因组(参见下文),那么Bpipe将省略这个用于指代整个染色体的区域,即不用指明这个区域的具体范围。
可选的基因组
当通过染色体并行运行时,参考序列(如染色体)的格式可以根据所用的参考基因组而变化。Bpipe的默认配置是使用UCSC的样式约定,即在参考序列之前使用“chr”作为前缀。要忽略这一点,或通知Bpipe基因组的其他方面,请在您的流程开始时声明您正在使用的基因组,如:genome 'GRCh37'
对于不包含“chr”前缀的基因组,Bpipe在计算$chr
和$region
变量时将使用正确的样式。
注:Bpipe将尝试从UCSC下载基因组的染色体大小。
在任意基因组区域上进行并行化
Bpipe还支持切分基因组,将基因组切分成任意区间来并行处理它们。当您希望以比染色体更小范围的方式并行运行时,这尤其有用(通常是必要的,因为染色体大小非常不均匀)。有两种方法可以切分基因组区域:
- 按间隔大小划分为均匀大小的区间(区间数量是动态的)
- 切分为特定数量的区间(区间大小是动态的)
Bpipe通过名为partition
和split
的命令支持这两种切分方法。
定义区域
如果要处理整个“基因组”,则可以使用genome
命令声明基因组,然后该基因组将当作一个区域。但是,如果要处理基因组的一个子集(例如外显子区域),则可以加载自定义BED文件:
my_regions = bed("/some/path/to/a/bed/file.bed")
按区间大小切分partition
要相同区间间隔切分区域,请使用partition
命令,然后接要进行并行处理的阶段列表。比如要在1 mb 的区间中处理所有的hg19基因组:
hg19.partition(1000000) * [ stage1 + stage2 ]
要处理自定义区域,使用方法是完全相同的:
my_regions.partition(1000000) * [ stage1 + stage2 ]
按区间数量切分split
要将区域切分为一定数量的区间,请使用split
命令:
hg19.split(40) * [ stage1 + stage2 ]
Bpipe将尝试创建40个相同大小的区间,但不会尝试过多。也就是说,如果您使用一组自定义区域,它将尝试将区域之间的差距一分为二,并且除非将比例减小到大于2:1,否则绝不会将它们分成两部分。这样,除非您切分到非常精细的级别,否则通常可以依靠Bpipe保留整个外显子和目标区域以用于定义想要的区间。
当切分整个基因组时,Bpipe将尝试从UCSC下载基因和外显子的定义区间。然后,创建的区域时它将避免切分到外显子或基因的区域(除非无法实现所需的粒度,以使所得区域大小之间的比例不超过2:1)。
branch名称
当您划分一组区域时,Bpipe会自动为每个并行路径分配一个分支名称。
- 如果区域是整个染色体或contig,则分支名称是染色体或contig的名称
- 否则,Bpipe计算区间的sha1哈希值,并将前8个字符作为分支名称
引用区间
可以在阶段内使用$region
变量来访问要处理的实际区域,或者如果需要BED文件,则通过$region.bed
访问。
合并结果
请参阅merge命令,为合并并行阶段的输出,Bpipe提供的特别支持命令。
在不同数据上同时执行多个阶段
在上面的示例中,每个并行阶段都接收相同的输入文件并一起对其进行操作。但是有时候,您真正想要的是让每个输入文件或输入一组输入文件独立地通过同一阶段(或多个阶段)。Bpipe将此称为输入拆分,并为您提供了一种简洁的方法来实现此目的。
假设我们有10个输入文件,并且希望同时处理所有10个名为input_1.txt到input_10.txt的文件。代码如下:
Bpipe.run {
"input_%.txt" * [ hello + world ] + nice_to_see_you
}
这里有两点需要注意:
- 流程的输入拆分模式从
%
字符开始,该模式表明使用文件的哪一部分对输入文件进行拆分。 - 流程使用
*
(或乘法),而不是常用的+
号
请注意,在运行流程时,Bpipe仍然需要您在命令行上指定要匹配的文件。匹配不是在文件系统中的文件上进行,而是在流程中的文件上进行。因此,如果将代码保存在名为“ helloworld.pipe”的文件中,则可以使用以下示例运行此示例:
bpipe run helloworld.pipe input*.txt
输入拆分模式
切分
Bpipe使用非常简单的通配符语法来定义您应如何将文件分为几组进行处理。在这些模式中,您只需用充当通配符(匹配任意数量的字符)的百分比符号,替换文件名要分组的那部分。匹配的文件将一起传递到并行阶段进行处理。
用于对文件进行分组的模式匹配是子字符串匹配。因此,您只需要提供足够的输入文件名即可唯一地标识分组字符所在的位置。例如,以下管道等同于上面的管道:
run {
"_%." * [ hello + world ] + nice_to_see_you
}
这意味着Bpipe将在文件名中查找第一个(也是最短的)标记,其左侧为下划线,右侧为一个句点(.
字符)。如果文件的名称部分差别很大,且与希望分组的方式无关,这种方式可能很有用。
注意:与分组运算符模式不匹配的文件将全部从输入中过滤掉。此功能很有用,可使的目录中包含作为输入文件在内的各种文件,即使其中一些不是真实的输入文件也没关系。Bpipe将根据您指定的模式筛选出所需的文件。
排序
Bpipe在其输入拆分模式中还支持另一个特殊字符:*
通配符。这也可以用作通配符进行匹配,但不会将输入文件分成几组。相反,它会影响被拆分组中的顺序。当Bpipe在输入拆分模式中匹配字符时,它首先将文件分为几组(基于%
匹配项),然后根据与该*
字符匹配的部分对它们进行排序。这可以帮助您确保即使拆分后文件仍保持合理的顺序。例如,考虑以下输入文件
input_1_1.txt
input_1_2.txt
input_2_2.txt
input_2_1.txt
您可以使用一种模式对输入进行拆分和排序:"input_%_*.txt"
然后,此模式将拆分并排序文件,如下所示:
第1组 : input_1_1.txt,input_1_2.txt
第2组 : input_2_1.txt,input_2_2.txt
请注意,第二组的文件顺序与原来的顺序相反,因为Bpipe对它们进行了排序。
明确指定并行路径
如果您不能从上述机制中灵活地指定输入文件,则可以通过指定Groovy的List或Map来告诉Bpipe所需的路径,明确地设置分支路径。使用Map时,映射中的键将解释为分支名称,映射中的值将解释为文件或文件列表,这些文件或文件列表将作为输入提供给分支。
例如:
// Create a data structure (Map) that maps branches to files
def branches = [
sample1: ["sample1_2.fastq.gz"],
sample2: ["sample2_2.fastq.gz"],
sample3: ["sample3_2.fastq.gz"]
]
align = {
// keep the sample name as a branch variable
branch.sample = branch.name
...
}
run { branches * [ align ] }
在此示例中,该align阶段将并行运行3次,并且将特定分支的文件显式地给align阶段。当然,在正常使用情况下,最好不要通过静态指定它们,而是当您想从文件或数据库或其他地方读取信息并从中构造branch时。
分配线程
有时您会事先确切知道您希望在一个命令中使用多少个线程。在这种情况下,使用procs
配置中的属性指定它,或者直接在管道阶段使用uses语句指定它。
但是,在其他时候,您希望更加灵活,并允许更动态地分配资源。这意味着,如果有更多可用的计算资源,则可以利用它,而当可用的计算资源不足时,您的流程可以使用更少的计算资源以正常运行。Bpipe通过特殊$threads
变量为此提供了一些功能。此变量可以以两种不同的方式运行:
- 当bpipe.config文件中
procs
配置有指定时,该$threads
变量将使用该值。 - 当
procs
配置未指定任何值时,Bpipe将通过-n
标志(默认为运行Bpipe的计算机上的内核数)根据当前未使用的线程来决定一个合理的值给$threads
。分配后,$threads
将映射给procs
配置,用于分配资源。
例如:
align_bwa = {
exec "bwa aln -t $threads ref.fa $input.fq"
}
在这里,Bpipe将为$threads
分配一个值,该值试图最佳利用可用u资源。例如,如果您正在使用的计算机上有32个核心,并且其中有4个并行执行的阶段,则只要每个阶段大约同时启动,就应该为每个阶段分配8个核心。
限制动态并发
Bpipe以某种微妙的方式实现了动态并发。当命令要求对$threads
变量取值时,Bpipe需要确定当前可用线程池应与哪些其他任务共享。如果它只是立即计算此值,则将尝试为第一个尝试使用$threads
的命令分配所有剩余的并发线程,而其他命令将没有可用线程。为了避免这种情况,当命令请求$threads
时,Bpipe会暂停当前分支并等待,直到流程中所有并行的路径要么正在执行任务,要么也请求$threads
。然后,线程在所有请求者之间分配,并公平分配。
通常,以上过程会导致将线程公平分配给有竞争的任务,但是您应该意识到,对于时间分散的任务,仍然会出现“贪婪”的行为。因此,Bpipe将为一个任务分配多少线程的上限可能很有用。您可以在bpipe.config中设置max_per_command_threads变量来实现。这将限制可以分配的线程总数。
另一种方法是通过procs
变量在命令配置中指定线程分配范围。例如,在上一个示例中,我们可以通过在bpipe.config中指定,为bwa保留2至8个线程:
commands {
bwa {
procs=2..8
}
}
这将使Bpipe可以将$threads
设置为2到8之间的任何值。
局限性
并行运行阶段时,应始终使用Bpipe指定的输出文件(为您定义为$output
变量),而不是对文件名进行硬编码。这是必需的,因为当您自己定义输出文件时,Bpipe会检测到文件的创建并将其解释为当前正在执行阶段的输出。但是,通过执行多个阶段,此检测可以将输出分配给错误的阶段,或者正确的阶段的错误实例。如果您希望对阶段(或阶段的一部分)输出的文件名进行“硬编码”,您仍然可以这样做,但是您应该通过使用produce
语句包装创建该输出的命令来做到这一点,例如:
hello = {
produce("hello.txt") {
exec "cp $input $output"
}
}
我们不建议这样做,因为如果不小心,最终可能会覆盖多个并行线程的输出文件。通常,只要有可能,就让Bpipe管理文件名,并给出提示使它们成为您想要的样子。
branch 变量
不同stage之间通常需要传递信息。通常,此信息的范围仅限于特定分支或流程的某一部分。Bpipe通过使用“branch变量”来支持这一点。
创建branch变量
管道的每个分支(包括根)都传递一个称为“branch”的隐式变量。如果引用,此变量的值将为该阶段的分支的名称。例如,如果您使用chr
命令按染色体进行了拆分,则分支名称就是为当前正在执行分支的染色体。如果按文件分割,则是分支名称是文件名,即分支接受的文件名(或文件的唯一部分)。
但是branch这个变量还充当您自己的属性的容器。因此,您可以使用常规Groovy代码在其上设置属性:
hello = {
branch.planet = "mars"
}
引用分支变量
一旦设置,分支变量就可以被分支的所有后续阶段(包括所有子分支)直接引用。该值可以作为branch
对象的属性引用,例如branch.planet
,但也可以不带branch.
前缀引用。例如,以下管道打印“ hello mars”:
hello = {
branch.planet = "mars"
}
world = {
exec """echo "Hello $planet" """
}
run { hello + world }