如何在 shell 块中声明新的 Nextflow 变量?

How to declare a new Nextflow variable in a shell block?

我目前正在编写我的第一个 Nextflow 管道,我尝试在脚本中声明一个新的 Nextflow 变量,但我无法做到。

我想设置一个变量 min_length,其值在文本文件中读取(使用 awk 解析),稍后在我的管道中使用该值作为参数。这是我试过的:

process get_min_len{

  input:
  file "./foo.tab"

  output:
  val length_min into min_len_channel

  shell:
  """
  !{length_min}=`awk '{if ($1=="!{params.bar}") {print $2}}' ./foo.tab`
  """
}

我收到此错误消息:

Error executing process > 'get_min_max_len'

Caused by:
  No such variable: length_min

(我也试过像这样初始化 min_length : min_length=0 但它也不起作用。)

有办法吗? 谢谢!

您可以使用 env 限定符来捕获 shell 变量。例如:

params.foo = "foo.tab"
params.bar = "bar"

foo = file( params.foo )


process get_min_len{

  input:
  path foo

  output:
  env length_min into min_len_channel

  shell:
  '''
  length_min="$(awk ' == "!{params.bar}" { print  }' "!{foo}")"
  '''
}

但是,自己定义一个 shell 变量然后捕获它并不能避免创建文件。 env 限定符只是在运行时将一些 syntactic-sugar 添加到您的 shell 脚本中,这样仍然会创建一个输出文件。使用上面的示例,我得到:

$ cat work/d4/37ad3bea12cb64089196744b6558bb/.command.sh 
#!/bin/bash -ue
length_min="$(awk ' == "bar" { print  }' "foo.tab")"

# capture process environment
set +u
echo length_min=$length_min > .command.env

因此,更好的方法是自己将值写入文件,然后让 Nextflow 从输出通道读取以获取值。您可以为此使用 map 运算符:

process get_min_len{

  input:
  path foo

  output:
  path "length_min.txt" into min_len_channel

  shell:
  '''
  awk ' == "!{params.bar}" { print  }' "!{foo}" > "length_min.txt"
  '''
}

min_len_channel.map { it.text.strip() }.view()

读取文件内容后,您可以调用 strip() 删除字符串开头和结尾的空格(空格、换行符等)。或者,如果您的变量可能需要以额外的空格开始或结束,那么 AWK 'printf' 您的字符串可能会更好,以避免首先使用换行符。

一般来说,除非您正在解析的文件很大,否则我会避免像这样的单独过程。如果你的输入文件只是一些简单的配置文件,你可能会逃避这样的事情:

foo = file( params.foo )

Channel
    .from( foo.text )
    .splitCsv(sep: '\t')
    .filter { col1, col2 -> col1 == params.bar }
    .map { col1, col2 -> col2 }
    .view()