我剛開始一直不理解
awk
的語法元潘,后來看師兄的代碼,加上天天敲君仆,有了點提高翩概。
師兄在 2020-07-03 常用有趣命令之?dāng)?shù)據(jù)處理 中總結(jié)了很多代碼,非常有用返咱!
我經(jīng)常記不住钥庇,用到時就會進(jìn)去復(fù)制下來。下面是一些簡單基礎(chǔ)的用法洛姑。
1. 內(nèi)置變量
$0
: 記錄變量上沐,表示當(dāng)前正在處理的記錄,理解為整行楞艾;
$n
: 字段變量参咙,其中n為整數(shù),且 n
大于1硫眯,表示第 n
個字段的值蕴侧,理解為第 n
列;
NF
: 當(dāng)前記錄的字段數(shù)(number of field)两入,理解為列數(shù)净宵;
NR
: 已經(jīng)讀入的記錄數(shù)(number of record),理解為行數(shù)裹纳;
FS
: 字段分隔符(field seperator)择葡,默認(rèn)列分隔符為空白,awk -F ","
即可設(shè)置為 ,
剃氧;
RS
: 記錄分隔符(record seperator)敏储;
OFS
: 輸出字段分隔符;
ORS
: 輸出記錄分隔符朋鞍;
FILENAM
: 正在處理的數(shù)據(jù)文件的名稱已添;
ARGIND
: 實現(xiàn)多個文件的操作,可以參考:AWK實現(xiàn)多文件讀取和處理滥酥、awk打開多個文件的方法更舞;
FNR
: 當(dāng)前文檔的記錄數(shù),多文件操作時使用坎吻。
- 去除最后一列
awk '{$NF="";print}' a.txt
尤其是每行列數(shù)不一樣時缆蝉,尤為實用,但每行最后會多出一個分隔符,可以用函數(shù)
gsub(/.$/,"")
進(jìn)行刪除返奉,也可以用管道| sed 's/.$//'
- 多文件操作
如:合并多個文件贝搁,并把每個文件的第一樣去除
awk '{if(FNR>1)print}' a.txt b.txt c.txt
2. 運算符
算術(shù)運算符
+
: 加;-
: 減芽偏;*
: 乘;/
: 除賦值運算符
+=
: 將前后兩個數(shù)值相加后的和賦給前面的變量
-=
: 將前后兩個數(shù)值相減后的差賦給前面的變量
*/
: 將前后兩個數(shù)值的乘積賦給前面的變量
/=
: 將前后兩個數(shù)值的商賦給前面的變量
關(guān)系運算符
>
弦讽、<
污尉、>=
、<=
往产、==
被碗、!=
這些都不用說了邏輯運算符
&&
: 邏輯與,前后兩個表達(dá)式的值全部為真時仿村,其運算結(jié)果為真
||
: 邏輯或锐朴,前后兩個表達(dá)式只要有一個為真,其運算結(jié)果為真
!
: 邏輯非蔼囊,表達(dá)式的值為假時焚志,其運算結(jié)果為真三目運算符
下面這個例子也用到了格式化輸出
>g1
AGTCAT
CATACG
GCACTC
AT
>g2
CCATCA
TCAGGC
C
>g3
ACCTTG
GGCC
$ awk '/^>/&&NR>1{print "";}{ printf "%s",/^>/ ? $0" ":$0 }' gene.fa
>g1 AGTCATCATACGGCACTCAT
>g2 CCATCATCAGGCC
>g3 ACCTTGGGCC$
可發(fā)現(xiàn)每個基因變成了一行兩列,第一列為id畏鼓,第二列為序列酱酬。
加上| awk '{print $1"\n"}'
即可變成正常的單行 fasta 序列;
若加上| awk '{a+=length($2)}END{print a}'
即可得出序列的大小云矫。
3. 函數(shù)
- 字符串函數(shù)
length()
: 返回字符串的長度
gsub()
: 替換所有出現(xiàn)的子串
substr()
: 截取指定長度的子串膳沽。
另外還有,字符串函數(shù)让禀,
index()
挑社、match()
、split()
巡揍、sub()
痛阻;算術(shù)函數(shù),int(x)
吼肥、sqrt(x)
录平、exp(x)
...... 用不到,暫且留個印象缀皱。
$ echo "0.9774563" | awk '{print int($1*10000+0.5)*0.01"%"}'
97.75%
4. 數(shù)組
以下兩行代碼都是利用 數(shù)組 實現(xiàn)【轉(zhuǎn)置】斗这,代碼是師姐網(wǎng)上找的,出處已經(jīng)找不到了啤斗。
awk '{for(i=1;i<=NF;i++){if(NR==1)res[i]=$i;else res[i]=res[i]" "$i}}END{for(j=1;j<=NF;j++){print res[j]}}' a.txt
# 有幾列就定義幾個數(shù)組元素表箭,運行每一行時對數(shù)組進(jìn)行重新定義
awk '{for(i=1;i<=NF;i=i+1){a[NR,i]=$i}}END{for(j=1;j<=NF;j++){str=a[1,j];for(i=2;i<=NR;i++){str=str" "a[i,j]}print str}}' a.txt
# 先是對每一個值按坐標(biāo)進(jìn)行定義數(shù)組,按坐標(biāo)把相同列的排成行钮莲,太慢了
Shell 的
join
命令可以聯(lián)接多個文件免钻,但需要進(jìn)行排序彼水,還總是會莫名報錯,結(jié)果不可靠极舔,awk
就很好使凤覆。
$ cat a.txt
gene2 noTF others
gene1 TF MYB
gene3 TF HD-ZIP
gene15 noTF others
$ cat b.txt
gene10 23 9
gene12 56 7
gene3 75 8
gene4 84 2
gene1 50 3
gene2 74 6
$ awk 'BEGIN{OFS="\t"}ARGIND==1{a[$1]=$0}ARGIND==2{if($1 in a)print a[$1],$2,$3; else print $1,"NA\tNA",$2,$3}' a.txt b.txt
gene10 NA NA 23 9
gene12 NA NA 56 7
gene3 TF HD-ZIP 75 8
gene4 NA NA 84 2
gene1 TF MYB 50 3
gene2 noTF others 74 6
5. 控制流
日常 | 2021-05-10 | 任意n個樣本表達(dá)量超過0.5視為表達(dá) 的一個例子:
awk '{a=0;for(i=2;i<=NF;i++){if($i>0.5)a++};if(a>=2)print}' a.tsv