写在前面
perl-oneliner诅咒:即如果你相对熟练perl-oneliner的撰写之后,你就学不会awk和sed.
-- CJ
以下全文转载,点击阅读原文,可见Balloon_vine简书
awk 命令使用记录awk 'BEGIN{Cnt=0}{if($0~/>/){Cnt=Cnt+1;tmp='>TriUnigene'Cnt; $0=tmp; print$0}else{print$0}}' file.fasta
# ID修改前
>TRINITY_DN8_c0_g1_i1 len=239 path=[0:0-238]
>TRINITY_DN78_c0_g1_i1 len=417 path=[0:0-416]
>TRINITY_DN53_c0_g1_i1 len=203 path=[0:0-202]
# ID修改后, 即使fasta文件序列有多行也可以使用
>TriUnigene1
>TriUnigene2
>TriUnigene3
若后续只需要用到序列,不需要ID的信息,就可以把ID信息完全修改掉
例2:简化fasta序列名字awk '{if($0~/>/){sub(/\..*/, '', $0); print$0}else{print$0}}' file.fasta
ID 修改前后对比
# 修改前
>Lycv20126160-mRNA-1.mrna1 gene=Lycv20126160-mRNA-1
>Lycv20064330-mRNA-1.mrna1 gene=Lycv20064330-mRNA-1
>Lycv20064340-mRNA-1.mrna1 gene=Lycv20064340-mRNA-1
# 修改后
>Lycv20126160-mRNA-1
>Lycv20064330-mRNA-1
>Lycv20064340-mRNA-1
例3,修改染色体名字,并保持染色体两位数字
修改fasta序列ID,ID加1同时字符部分替换为Chr,并保持两位数值grep '>' Litchi_BMerged2A.genome.fna | awk '{if($0~/>/){split($0,a,'group');b=a[2]+1;if(length(b)<2){c='0'b}else{c=b};ID='>Chr'c;print ID}else{print$0}}'
>Bmerged2A_group0 >Chr01
>Bmerged2A_group10 >Chr11
>Bmerged2A_group11 >Chr12
>Bmerged2A_group12 >Chr13
>Bmerged2A_group13 >Chr14
>Bmerged2A_group14 >Chr15
>Bmerged2A_group1 >Chr02
>Bmerged2A_group2 >Chr03
>Bmerged2A_group3 >Chr04
>Bmerged2A_group4 >Chr05
>Bmerged2A_group5 >Chr06
>Bmerged2A_group6 >Chr07
>Bmerged2A_group7 >Chr08
>Bmerged2A_group8 >Chr09
>Bmerged2A_group9 >Chr10
其他
以下是其他一些情况的修改记录(笔者自己需要而写)
使用awk内置函数gsub
将 >Bradi1g47160.1.v3.1 替换为 >Bradi1g47160.1
awk '{if($0~/>/){gsub(/\.v3\.1/,'',$0);print$0}else{print$0}}' Brachypodium_distachyon.genome.modID.promoter
大小写转换,将>Glyma.01G073300.1.Wm82.a2.v1 + Up_Stream_Len 2500转为>Glyma01g073300.1awk '{if($0~/>/){gsub(/\.Wm82\.a2\.v1.*/,'',$0);split($0,a,'.');a[2]=tolower(a[2]);$0=a[1]a[2]'.'a[3];print$0}else{print$0}}'
使用awk内置split函数,用来分隔字符
time='AB:12:ab'
out=`echo $time | awk '{split($0,a,':');print a[1],a[2],a[3]}'`
echo $out
print打印中,以点号','间隔表示以输出分隔符(可以通过OFS指定)打印,以空格符号' '表示不以分隔符打印
awk 数组模式,
一、保留某字符特定前几行,命令表示只读取第一个字段第一次出现的行。awk '{array[$1]++; if(array[$1]==1) print $0}' $sample注: length为awk中的保留字符,不能拿来赋值
二、利用数组简单统计重复序列信息,BMerged2A.genome.fna.out为RepeatMask的输出结果
tail -n +3 Litchi_BMerged2A.genome.fna.out | awk 'BEGIN{print 'Repeat','Numbers','Length'}{tmp=$7-$6+1;arrayA[$11]+=tmp;arrayB[$11]++}END{for(key in arrayA)print key,arrayB[key],arrayA[key]}'
tail -n + 3表示不读取前三行,输出结果如下,由于循环问题,第二行(脚本额外生成)需要删除Repeat Numbers Length
1 1
LINE/L1 5508 3839687
Low_complexity 36060 1806624
DNA/hAT-Ac 1937 1019348
LTR/Gypsy 33902 61287663
Unknown 414560 137820270
LTR/Caulimovirus 1791 2250335
DNA/MuLE-MuDR 10824 10377274
LTR/Copia 21074 19759528
DNA/hAT-Tip100 1524 507589
DNA/hAT-Tag1 2248 1570480
DNA/CMC-EnSpm 2550 2237982
Simple_repeat 205035 12197075
DNA/PIF-Harbinger 2334 1025453
awk调用外部变量
tips1: 当调用的外部变量位置是在awk主句之中时,此时外部变量需要用括号内字符('''')去调用,如下例子:
str=Hello
awk 'BEGIN{print ''$str''}'
awk 'BEGIN{tmp=''$str'';print tmp}'
# 以下7种都是错误引用形式
awk 'BEGIN{print '$str'}'
awk 'BEGIN{print '$str'}'
awk 'BEGIN{print ''$str''}'
awk 'BEGIN{print ''$str''}'
awk 'BEGIN{print ''$str''}'
awk 'BEGIN{print '$str'}'
awk 'BEGIN{print '$str'}'
tips2: 当调用的外部变量位置是在awk内部函数之中时,如if, split, sub等,只可使用如下两种形式:Str=EVM
awk '{if($2~/'$Str'/)print$0}' Litchi_BMerged2A.gff3 | cut -f2 | sort | uniq
awk '{if($2~/''$Str''/)print$0}' Litchi_BMerged2A.gff3 | cut -f2 | sort | uniq
第二部分 sed 命令
sed字符替换中使用变量
eval sed 's/$a/$b/' filename
sed 's/$a/$b/' filename
sed 's/'$a'/'$b'/' filename
sed s/$a/$b/ filename
# 全词匹配
sed 's/\/new/g' file
# 替换多个空格为一个,注意前面括号里面为空格
sed 's/[ ][ ]*/ /g'
# sed删除倒数n行
linenum=`cat file | wc -l`
linenum_last3=`expr $linenum - 4`
sed -n '''$linenum_last3''d' file
提取字符串,正则表达式匹配某字符串后,字符串某一部分保留为元组,然后打印echo here365test | sed 's/.*ere\([0-9]*\).*/\1/g'
替换换行符,然后转为数学表达式并计算其值,
echo -e '3\n5\n6' |sed ':a;N;s/\\n/+/g;ba' | bc