Nextflow的脚本语言是Groovy的拓展。
语言基础
变量
x = 1
println x
x = new java.util.Date()
println x
x = -3.1499392
println x
x = false
println x
x = "Hi"
println x
列表
myList = [1776, -1, 33, 99, 0, 928734928763]
println myList[0]
println myList.size()
映射
scores = [ "Brett":100, "Pete":"Did not finish", "Andrew":86.87934 ]
获取
println scores["Pete"]
println scores.Pete
增加或修改
scores["Pete"] = 3
scores["Cedric"] = 120
一次声明多个变量
(a, b, c) = [10, 20, 'foo']
assert a == 10 && b == 20 && c == 'foo'
条件控制
x = Math.random()
if( x < 0.5 ) {
println "You lost."
}
else {
println "You won!"
}
字符串
println "he said 'cheese' once"
println 'he said "cheese!" again'
字符串连接
a = "world"
print "hello " + a + "\n"
变量内插
单引号和双引号的区别在于,双引号支持变量内插
foxtype = 'quick'
foxcolor = ['b', 'r', 'o', 'w', 'n']
println "The $foxtype ${foxcolor.join()} fox"
x = 'Hello'
println '$x + $y'
会得到结果
The quick brown fox
$x + $y
多行字符串
text = """
hello there James
how are you today?
"""
在Bash中
myLongCmdline = """ blastp \
-in $input_query \
-out $output_file \
-db $blast_database \
-html
"""
result = myLongCmdline.execute().text
闭包
其中it为占位符
square = { it * it }
定义之后,可用于调用
println square(9)
使用collect函数
[ 1, 2, 3, 4 ].collect(square)
那么会得到
[ 1, 4, 9, 16 ]
也可以使用多个参数
printMapClosure = { key, value ->
println "$key = $value"
}
[ "Yue" : "Wu", "Mark" : "Williams", "sudha" : "Kumari" ].each(printMapClosure)
那么会得到
Yue=Wu
Mark=Williams
Sudha=Kumari
myMap = ["China": 1 , "India" : 2, "USA" : 3]
result = 0
myMap.keySet().each( { result+= myMap[it] } )
println result
具体应该是参考 Groovy 的 文档
看几个示例,就可以了,其实有点像Perl
assert 'foo' =~ /foo/ // return TRUE
assert 'foobar' =~ /foo/ // return TRUE
assert 'foo' ==~ /foo/ // return TRUE
assert 'foobar' ==~ /foo/ // return FALSE
x = ~/abc/
println x.class
// prints java.util.regex.Pattern
y = 'some string' =~ /abc/
println y.class
// prints java.util.regex.Matcher
字符串替换
x = "colour".replaceFirst(/ou/, "o")
println x
// prints: color
y = "cheesecheese".replaceAll(/cheese/, "nice")
println y
// prints: nicenice
字符串捕获
似乎跟perl没啥区别
programVersion = '2.7.3-beta'
m = programVersion =~ /(\d+)\.(\d+)\.(\d+)-?(.+)/
assert m[0] == ['2.7.3-beta', '2', '7', '3', 'beta']
assert m[0][1] == '2'
assert m[0][2] == '7'
assert m[0][3] == '3'
assert m[0][4] == 'beta'
还可以直接捕获并赋予变量
programVersion = '2.7.3-beta'
(full, major, minor, patch, flavor) = (programVersion =~ /(\d+)\.(\d+)\.(\d+)-?(.+)/)[0]
println full // 2.7.3-beta
println major // 2
println minor // 7
println patch // 3
println flavor // beta
基于模式去除字符串部分
// define the regexp pattern
wordStartsWithGr = ~/(?i)\s+Gr\w+/
// apply and verify the result
('Hello Groovy world!' - wordStartsWithGr) == 'Hello world!'
('Hi Grails users' - wordStartsWithGr) == 'Hi users'
assert ('Remove first match of 5 letter word' - ~/\b\w{5}\b/) == 'Remove match of 5 letter word'
assert ('Line contains 20 characters' - ~/\d+\s+/) == 'Line contains characters'
文件和I/O
myFile = file('some/path/to/my_file.file')
类似bash,支持路径通配
listOfFiles = file('some/path/*.fa')
可以使用一些参数
listWithHidden = file('some/path/*.fa', hidden: true)
事实上,这个是一个Java的Path对象。
基本的读写
上述已经介绍了File对象的获取,有了file对象,可以打印其text属性(事实上,这个属性是整个文本的内容变成一个字符串)
print myFile.text
也可以对该属性赋值,这一赋值会直接重写文件内容
myFile.text = 'Hello world!'
也可以对已经存在的文件,追加内容
myFile.append('Add this line\n')
或者使用
myFile << 'Add a line more\n'
对于二进制数据
binaryContent = myFile.bytes
或者
myFile.bytes = binaryBuffer
逐行读取文件
一次性读取文件
myFile = file('some/my_file.txt')
allLines = myFile.readLines()
for( line : allLines ) {
println line
}
更优雅的使用方式,
file('some/my_file.txt')
.readLines()
.each { println it }
上述会读入整个文件,无法处理大文件,推荐使用
count = 0
myFile.eachLine { str ->
println "line ${count++}: $str"
}
增强的文件读取操作
可以创建Reader
或者InputStream
对象,那么就可以使用更多的读取方法
myReader = myFile.newReader()
String line
while( line = myReader.readLine() ) {
println line
}
myReader.close()
myFile.withReader {
String line
while( line = myReader.readLine() ) {
println line
}
}
增强的输出操作
将文件的中的U全部替换为X
sourceFile.withReader { source ->
targetFile.withWriter { target ->
String line
while( line=source.readLine() ) {
target << line.replaceAll('U','X')
}
}
}
列出文件夹内容
myDir = file('any/path')
allFiles = myDir.list()
for( def file : allFiles ) {
println file
}
遍历操作
myDir.eachFile { item ->
if( item.isFile() ) {
println "${item.getName()} - size: ${item.size()}"
}
else if( item.isDirectory() ) {
println "${item.getName()} - DIR"
}
}
创建目录
myDir = file('any/path')
result = myDir.mkdir()
println result ? "OK" : "Cannot create directory: $myDir"
创建多级目录
myDir.mkdirs()
创建链接
myFile = file('/some/path/file.txt')
myFile.mklink('/user/name/link-to-file.txt')
复制文件
myFile.copyTo('new_name.txt')
文件夹会自动复制内容
myDir = file('/some/path')
myDir.copyTo('/some/new/path')
移动文件
myFile = file('/some/path/file.txt')
myFile.moveTo('/another/path/new_file.txt')
移动或者重命名该文件夹,表现与linux
的mv
一致
myDir = file('/any/dir_a')
myDir.moveTo('/any/dir_b')
文件重命名
myFile = file('my_file.txt')
myFile.renameTo('new_file_name.txt')
删除文件
myFile = file('some/file.txt')
result = myFile.delete
println result ? "OK" : "Can delete: $myFile"
如果是要删除非空文件夹,那么使用deleteDir
查看文件属性
获取或者修改文件属性
permissions = myFile.getPermissions()
myFile.setPermissions('rwxr-xr-x')
或者
myFile.setPermissions(7,5,5)
HTTP/FTP文件
pdb = file('http://files.rcsb.org/header/5FID.pdb')
随后当成本地文件处理即可
println pdb.text