Linux命令awk,sed使用

写在前面

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.1

awk '{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.outRepeatMask的输出结果

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/\<old\>/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

(0)

相关推荐