Nextflow Scripts
Nextflow腳本語言是Groovy編程語言的擴展莺奸。Groovy是Java虛擬機的強大編程語言惯疙。Nextflow語法專門用于以聲明方式簡化計算流水線的編寫。
Nextflow可以執(zhí)行任何Groovy代碼或使用任何庫用于JVM平臺骂因。
有關Groovy編程語言的詳細說明方庭,請參考以下鏈接:
您可以在下面找到Nextflow腳本語言中使用的最重要的語言結(jié)構(gòu)的速成課程翩瓜。
警告
Nextflow UTF-8用作源文件和應用程序文件的默認文件字符編碼跨扮。使用UTF-8您喜歡的文本編輯器編輯Nextflow腳本時序无,請務必使用編碼验毡。
1.Language basics
1.1 Hello world
使用print或println方法即可:
println "Hello, World!"
兩者之間的唯一區(qū)別是該println方法隱式地將新行字符附加到打印字符串。
1.2 變量
要定義變量帝嗡,只需為其賦值:
x = 1
println x
x = new java.util.Date()
println x
x = -3.1499392
println x
x = false
println x
x = "Hi"
println x
1.3 Lists
可以通過將列表項放在方括號中來定義List對象:
myList **=** [1776, **-**1, 33, 99, 0, 928734928763]
您可以使用方括號表示法訪問列表中的給定項目(索引從0開始):
println myList[0]
為了獲得列表的長度晶通,請使用以下size方法:
println myList**.**size()
詳細了解列表:
1.4 Maps
Maps 用于存儲關聯(lián)數(shù)組或詞典。它們是異構(gòu)的命名數(shù)據(jù)的無序集合:
scores = [ "Brett":100, "Pete":"Did not finish", "Andrew":86.87934 ]
請注意哟玷,存儲在map中的每個值可以是不同的類型狮辽。Brett是一個整數(shù),Pete是一個字符串巢寡,Andrew是一個浮點數(shù)喉脖。
我們可以通過兩種主要方式訪問map中的值:
println scores["Pete"]
println scores.Pete
要向map添加數(shù)據(jù)或修改map,語法類似于向列表添加值:
scores["Pete"] = 3
scores["Cedric"] = 120
詳細了解map:
1.5 Multiple assignment
數(shù)組或列表對象可用于一次分配多個變量:
(a, b, c) = [10, 20, 'foo']
assert a == 10 && b == 20 && c == 'foo'
賦值運算符左側(cè)的三個變量由列表中的相應項初始化抑月。
1.6 條件執(zhí)行
任何編程語言最重要的特性之一是能夠在不同條件下執(zhí)行不同的代碼动看。最簡單的方法是使用if構(gòu)造:
x = Math.random()
if( x < 0.5 ) {
println "You lost."
}else {
println "You won!"
}
1.7 Strings
可以通過用單引號或雙引號('或"字符)括起文本來定義字符串:
println "he said 'cheese' once"
println 'he said "cheese!" again'
字符串可以與+以下內(nèi)容連接:
a = "world"
print "hello " + a + "\n"
1.8 String interpolation
單引號和雙引號字符串之間存在重要差異:雙引號字符串支持變量插值,而單引號字符串則不支持爪幻。
實際上,雙引號字符串可以包含任意變量的值须误,方法是在其名稱前加上{expression}語法表示任何表達式的值,類似于Bash / shell腳本:
foxtype = 'quick'
foxcolor = ['b', 'r', 'o', 'w', 'n']
println "The $foxtype ${foxcolor.join()} fox"
x = 'Hello'
println '$x + $y'
/* 結(jié)果 */
The quick brown fox
$x + $y
1.9 Multi-line strings
跨越多行的文本塊可以通過用三個單引號或雙引號分隔來定義:
text = """
hello there James
how are you today?
"""
注意:
與之前一樣京痢,雙引號內(nèi)的多行字符串支持變量插值奶甘,而單引號多行字符串則不支持。
與在Bash / shell腳本中一樣祭椰,在帶有\(zhòng)字符的多行字符串中終止一行會阻止新行字符將該行與后面的行分開:
myLongCmdline **=** """ blastp \
-in $input_query \
-out $output_file \
-db $blast_database \
-html
"""
result = myLongCmdline.execute().text
在前面的示例中臭家,blastp的-in和-out,-db和-html開關及其參數(shù)實際上是一行方淤。
2 Closures
簡而言之钉赁,閉包是一個代碼塊,可以作為參數(shù)傳遞給函數(shù)携茂。因此你踩,您可以定義一大塊代碼,然后將其傳遞讳苦,就像它是字符串或整數(shù)一樣带膜。
更正式地說,您可以創(chuàng)建定義為第一類對象的函數(shù)鸳谜。
square = { it * it }
表達式周圍的大括號告訴腳本解釋器將此表達式視為代碼膝藕。it標識符是一個隱式變量,表示調(diào)用時傳遞給函數(shù)的值咐扭。
編譯完成后芭挽,函數(shù)對象將被分配給square變量滑废,就像之前顯示的任何其他變量賦值一樣。現(xiàn)在我們可以這樣做:
println square(9)
并獲得值81览绿。
我們可以將函數(shù)square作為參數(shù)傳遞給其他函數(shù)或方法策严。一些內(nèi)置函數(shù)將這樣的函數(shù)作為參數(shù)。一個例子是collect列表上的方法:
[ 1, 2, 3, 4 ].collect(square)
這個表達式說:創(chuàng)建一個值為1,2,3和4的數(shù)組饿敲,然后調(diào)用它的collect方法妻导,傳入我們上面定義的閉包。該collect方法遍歷數(shù)組中的每個項目怀各,調(diào)用定義好的閉包倔韭,然后將結(jié)果放入新數(shù)組中,從而產(chǎn)生:
[ 1, 4, 9, 16 ]
有關可以使用閉包作為參數(shù)調(diào)用的更多方法瓢对,請參閱 :
http://docs.groovy-lang.org/latest/html/groovy-jdk/ 寿酌。
默認情況下,閉包會調(diào)用一個參數(shù)it硕蛹,但您也可以創(chuàng)建具有多個自定義命名參數(shù)的閉包醇疼。例如,該方法Map.each()可以采用帶有兩個參數(shù)的閉包法焰,它將鍵綁定到值秧荆,并為該鍵中的每個鍵值對關聯(lián)值Map。在這里埃仪,我們使用明顯的變量名稱key并value在我們的閉包中:
printMapClosure ={ key, value ->
println "$key = $value"}
[ "Yue": "Wu", "Mark": "Williams", "Sudha": "Kumari" ].each(printMapClosure)
打右冶簟:
Yue=Wu
Mark=Williams
Sudha=Kumari
封閉物還有另外兩個重要特征。首先卵蛉,它可以訪問定義它的范圍內(nèi)的變量颁股,以便它可以與它們進行交互。
其次傻丝,閉包可以以匿名方式定義甘有,這意味著它沒有給出名稱,并且在需要使用它的地方定義葡缰。
作為顯示這兩個功能的示例梧疲,請參閱以下代碼片段:
myMap = ["China": 1, "India": 2, "USA": 3]
result = 0
myMap.keySet().each( { result += myMap[it] } )
println result
在Groovy文檔中了解有關閉包的更多信息:http://groovy-lang.org/closures.html .
3. Regular expressions
正則表達式是瑞士軍刀級別的文本處理方法。它們?yōu)槌绦騿T提供了匹配和提取字符串模式的能力运准。
通過 ~/pattern/ 語法 =~ 和 ==~ 運算符可以使用正則表達式幌氮。
使用 =~ 檢查給定模式是否在字符串中的任何位置發(fā)生:
assert 'foo' =~ /foo/ // return TRUE
assert 'foobar' =~ /foo/ // return TRUE
使用 ==~ 檢查字符串是否與給定的正則表達式模式完全匹配。
assert 'foo' ==~ /foo/ // return TRUE
assert 'foobar' ==~ /foo/ // return FALSE
值得注意的是胁澳,~ 運算符從給定的字符串創(chuàng)建Java Pattern對象该互,而 =~ 運算符創(chuàng)建Java Matcher對象。
x = ~/abc/
println x.class
// prints java.util.regex.Pattern
y = 'some string' =~ /abc/
println y.class
// prints java.util.regex.Matcher
正則表達式支持從Java導入韭畸。Java的正則表達式語言和API在Pattern Java文檔中有記錄宇智。
你可能也對這篇文章感興趣:Groovy:
3.1 String replacement
要替換給定字符串中的模式出現(xiàn)次數(shù),請使用replaceFirst和replaceAll方法:
x = "colour".replaceFirst(/ou/, "o")
println x
// prints: color
y = "cheesecheese".replaceAll(/cheese/, "nice")
println y
// prints: nicenice
3.2 Capturing groups
您可以匹配包含組的模式随橘。首先使用 =~ 運算符創(chuàng)建匹配器對象喂分。然后,您可以索引匹配器對象以查找匹配項:matcher[0]返回表示字符串中正則表達式的第一個匹配項的列表机蔗。第一個列表元素是與整個正則表達式匹配的字符串蒲祈,其余元素是與每個組匹配的字符串。
以下是它的工作原理:
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
3.3 Removing part of a string
您可以使用正則表達式模式刪除部分String值梆掸。找到的第一個匹配項將替換為空字符串:
// 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'
從字符串中刪除第一個5個字符的單詞:
assert ('Remove first match of 5 letter word' - ~/\b\w{5}\b/) == 'Remove match of 5 letter word'
從字符串中刪除帶有尾隨空格的第一個數(shù)字:
assert ('Line contains 20 characters' - ~/\d+\s+/) == 'Line contains characters'
4. Files and I/O
要訪問和使用文件,請使用該file方法牙言,該方法在給定文件路徑字符串的情況下返回文件系統(tǒng)對象:
myFile = file('some/path/to/my_file.file')
該file方法可以引用文件或目錄酸钦,具體取決于文件系統(tǒng)中字符串路徑引用的內(nèi)容。
使用通配符 * 時 ? 咱枉,[] 和 {} 卑硫,該參數(shù)被解釋為glob路徑匹配器,并且該file方法返回一個列表對象蚕断,其中包含名稱與指定模式匹配的文件的路徑拔恰,如果找不到匹配項則返回空列表:
listOfFiles = file('some/path/*.fa')
注意
glob模式中的兩個星號(**)與 * 類似,但匹配文件系統(tǒng)路徑中的任意數(shù)量的目錄組件基括。
默認情況下,通配符與目錄或隱藏文件不匹配财岔。例如风皿,如果要在結(jié)果列表中包含隱藏文件,請?zhí)砑涌蛇x參數(shù)hidden:
listWithHidden = file('some/path/*.fa', hidden: true)
以下是file可用選項:
名稱 描述
glob -- 當true時匠璧,將字符*桐款,?夷恍,[]和{}解釋為glob通配符魔眨,否則將它們作為普通字符處理(默認值:true)
type 返回的路徑類型,要么file酿雪,dir或any(默認值:file)
hidden -- 當true時遏暴,能返回隱藏文件(默認值:false)
maxDepth -- 要訪問的最大目錄級別數(shù)(默認值:無限制)
followLinks -- 當true時,可以遍歷符號鏈接指黎,否則將它們視為文件(默認:true)
checkIfExists -- 當true時朋凉,若拋出指定路徑不存在則拋出異常(默認值:false)
注意
如果您是Java極客,您將有興趣知道該file方法返回一個Path對象醋安,它允許您使用Java程序中常用的方法杂彭。
另請參見:Channel.fromPath墓毒。
4.1 Basic read/write
給定一個文件變量,使用file前面示例中顯示的方法聲明亲怠,讀取文件就像獲取文件text屬性的值一樣簡單所计,該屬性將文件內(nèi)容作為字符串值返回:
print myFile.text
同樣,您只需將字符串值保存到文件的text屬性即可將其保存到文件中:
myFile.text = 'Hello world!'
注意
現(xiàn)有文件在被操作時团秽,其原始內(nèi)容會被覆蓋主胧,該操作也隱式創(chuàng)建不存在的文件。
為了在不刪除現(xiàn)有內(nèi)容的情況下將字符串值附加到文件徙垫,您可以使用以下append方法:
myFile.append('Add this line\n')
或者使用左移運算符讥裤,這是一種將文本內(nèi)容附加到文件的更慣用的方法:
myFile << 'Add a line more\n'
二進制數(shù)據(jù)可以以相同的方式處理,只使用file的bytes屬性而不是text姻报。因此己英,以下示例讀取文件并將其內(nèi)容作為字節(jié)數(shù)組返回:
binaryContent = myFile.bytes
或者您可以將字節(jié)數(shù)組數(shù)據(jù)緩沖區(qū)保存到文件中,只需編寫:
myFile.bytes = binaryBuffer
警告
上述方法在單個變量或緩沖區(qū)中一次讀寫所有文件內(nèi)容吴旋。因此损肛,在處理需要更高內(nèi)存效率的大文件時,不建議使用它們荣瑟,例如逐行讀取文件或使用固定大小的緩沖區(qū)治拿。
4.2 Read a file line by line
為了逐行讀取文本文件,您可以使用readLines()文件對象提供的方法笆焰,該方法將文件內(nèi)容作為字符串列表返回:
myFile = file('some/my_file.txt')
allLines = myFile.readLines()
for( line: allLines ) {
println line
}
這也可以用更慣用的語法編寫:
file('some/my_file.txt')
.readLines()
.each{ println it }
注意
該readLines()方法一次性讀取所有文件內(nèi)容并返回包含所有行的列表劫谅。因此,請勿使用它來讀取大文件嚷掠。
要處理大文件捏检,請使用該方法eachLine,該方法一次只讀取一行到內(nèi)存中:
count = 0
myFile.eachLine { str ->
println "line ${count++}: $str"
}
4.3 Advanced file reading operations
類Reader和InputStream可以操作文本和二進制文件.
該newReader方法為給定文件創(chuàng)建一個Reader對象不皆,允許您將內(nèi)容讀取為單個字符贯城,行或字符數(shù)組:
myReader = myFile.newReader()
String line
while( line = myReader.readLine() ) {
println line
}
myReader.close()
newReader方法為給定文件創(chuàng)建一個Reader對象,允許您將內(nèi)容讀取為單個字符霹娄,行或字符數(shù)組::
myReader = myFile.newReader()
String line
while( line = myReader.readLine() ) {
println line
}
myReader.close()
newInputStream和withInputStream方法的工作方式類似能犯。主要區(qū)別在于它們創(chuàng)建了一個用于編寫二進制數(shù)據(jù)的InputStream對象。
以下是從文件中讀取的最重要方法:
"待補充"
閱讀Reader和 InputStream類的Java文檔犬耻,以了解有關可用于從文件讀取數(shù)據(jù)的方法的更多信息踩晶。