脚本

脚本是字符串声明,它定义了由过程执行到执行任务的命令。

一个进程仅包含一个脚本块,并且当该进程包含输入和输出声明时,它必须是最后一个语句。

输入的字符串在主机系统中作为Bash脚本执行。它可以是通常在终端 shell 程序或通用Bash脚本中使用的任何命令,脚本或它们的组合。

可以在脚本语句中使用的命令的唯一限制是目标执行系统中这些程序的可用性。

脚本可以是简单字符串或多行字符串,例如:

process doMoreThings {

"""
blastp -db $db -query query.fa -outfmt 6 > blast_result
cat blast_result | head -n 10 | cut -f 2 > top_hits
blastdbcmd -db $db -entry_batch top_hits > sequences
"""

}

可以使用单引号或双引号定义字符串,并使用三个单引号或三个双引号字符定义多行字符串。

需要注意,在Bash中,以字符分隔的字符串"支持变量替换,而以字符分隔的字符串'则不支持。

在上面的代码片段中,$db变量被替换为管道脚本中已经定义的实际值。

需要在脚本中访问系统环境变量时,有两个选择。

  • 首选就像使用单引号字符串定义脚本块一样容易。例如:
process printPath {

'''
echo The path is: $PATH
'''

}

该解决方案的缺点是,您将无法在脚本中访问在管道脚本上下文中定义的变量。

  • 要解决此问题,请使用双引号字符串定义脚本,并通过在系统环境变量前添加反斜杠字符来对其进行转义\,如以下示例所示:
process doOtherThings {

"""
blastp -db \$DB -query query.fa -outfmt 6 > blast_result
cat blast_result | head -n $MAX | cut -f 2 > top_hits
blastdbcmd -db \$DB -entry_batch top_hits > sequences
"""

}

在此示例中,$MAX必须在管道脚本定义变量。 在执行脚本之前,Nextflow用实际值替换它。

$DB变量必须存在于脚本执行环境中,并且Bash解释器将其替换为实际值。

另外,可以使用Shell块定义,该定义允许脚本包含Bash和Nextflow变量,而不必转义第一个。

使用其他语言的脚本

默认情况下,Nextflow流程脚本为Bash脚本,但您不仅限于此。

您可以使用自己喜欢的脚本语言(例如Perl,Python,Ruby,R等),甚至可以将它们混合在同一管道中。

管道可以由执行不同的任务的进程组成。使用Nextflow,您可以选择更适合指定进程执行的任务的脚本语言。

例如,对于某些进程,R可能比Perl有用,在其他进程中,您可能需要使用Python,因为它提供了对库或API等的更好访问。

要使用Bash以外的脚本,只需使用相应的shebang声明启动流程脚本 。例如:

process perlStuff {

"""
#!/usr/bin/perl

print 'Hi there!' . '\n';
"""

}

process pyStuff {

"""
#!/usr/bin/python

x = 'Hello'
y = 'world!'
print "%s - %s" % (x,y)
"""

}

由于解释器二进制文件的实际位置可以在各个平台上变化,因此为了使脚本更易于移植,在声明时,使用#!/usr/bin/env perl。这是使用envshell命令,后跟解释器的名称,而不是其绝对路径。

根据条件执行不同脚本

复杂的过程脚本可能需要评估对输入参数的条件,或使用传统的流量控制语句(即ifswitch等),根据当前输入的配置,以执行特定的脚本命令。

流程脚本可以通过简单地在脚本块前面加上关键字来包含条件语句script:

然后,解释器将评估以下所有语句作为必须返回要执行的脚本字符串的代码块。例如:

seq_to_align = ...
mode = 'tcoffee'

process align {
input:
file seq_to_aln from sequences

script:
if( mode == 'tcoffee' )
"""
t_coffee -in $seq_to_aln > out_file
"""

else if( mode == 'mafft' )
"""
mafft --anysymbol --parttree --quiet $seq_to_aln > out_file
"""

else if( mode == 'clustalo' )
"""
clustalo -i $seq_to_aln -o out_file
"""

else
error "Invalid alignment mode: ${mode}"

}

在上面的示例中,该过程将根据mode参数的值执行脚本片段。默认情况下它将执行tcoffee命令,将mode变量更改为mafftor clustalo值,其他分支将被执行。

模板

可以使用模板文件将流程脚本外部化,该模板文件可以在不同的流程之间重复使用,并且可以通过整体管道执行独立地进行测试。

模板只是Nextflow可以通过使用如下template功能执行的shell脚本文件:

process template_example {

input:
val STR from 'this', 'that'

script:
template 'my_script.sh'

}

Nextflow my_script.sh在目录templates中寻找模板文件,该目录必须存在于Nextflow脚本文件所在的文件夹中(可以使用绝对模板路径提供任何其他位置)。

模板脚本可以包含基础系统可以执行的任何代码。例如:

#!/bin/bash
echo "process started at `date`"
echo $STR
:
echo "process completed"

注意$,当脚本作为Nextflow模板运行时,$被解释为Nextflow变量占位符,而单独运行时,被评估为Bash变量。这对于自主地(即独立于Nextflow执行)测试脚本非常有用。

您只需为脚本中存在的每个Nextflow变量提供一个Bash环境变量。例如,可以在shell终端中输入以下命令来执行上述脚本:STR='foo' bash templates/my_script.sh

shell

shell块是一个字符串语句,用于定义由进程执行以执行其任务的shell命令。它是Script定义的替代方案,但有重要区别,它使用感叹号!字符作为Nextflow变量的变量占位符,代替了通常的美元字符。

这样,可以在同一段代码中同时使用Nextflow和Bash变量,而不必逃避后者,并使流程脚本更具可读性和易于维护。例如:

process myTask {

input:
val str from 'Hello', 'Hola', 'Bonjour'

shell:
'''
echo User $USER says !{str}
'''

}

在上面的琐碎示例中,$USER变量由Bash解释器管理,而!{str}作为由Nextflow管理的流程输入变量进行处理。

注意

  • Shell脚本定义要求使用单引号'分隔的字符串。使用双引号" 分隔的字符串时,美元变量照常解释为Nextflow变量。请参阅字符串插值
  • 感叹号前缀变量始终需要用大括号括起来,即被忽略!{str}!str是有效变量。
  • Shell脚本支持使用文件模板机制。相同的规则适用于脚本模板中定义的变量。

本机执行

Nextflow进程可以执行除系统脚本以外的本机代码,如前几段所示。

这意味着,您无需指定要作为字符串脚本执行的process命令,而是可以提供一种或多种语言语句来定义它,就像在其余管道脚本中一样。只需使用exec:关键字启动脚本定义块,例如:

x = Channel.from( 'a', 'b', 'c')

process simpleSum {
input:
val x

exec:
println "Hello Mr. $x"
}

将显示:

Hello Mr. b
Hello Mr. a
Hello Mr. c