Linux文本处理三架马车之二 awk

参考https://www.cnblogs.com/irockcode/p/6700135.html

范例

$ echo "Linux" | awk '{printf "|%-15s|\n",$1}'

|Linux     |

说明:对于echo命令的输出,Linux是经管道发给awk。printf函数包含一个控制串。百分号让printf做好准备,它要打印一个占15个格、向左对齐的字符串,这个字符串夹在两个竖杠之间,并且以换行符结尾。百分号后的短划线表示左对齐。控制串后面跟了一个逗号和$1。printf将根据控制串中的格式说明来格式化字符串Linux。

范例

$ echo "Linux" | awk '{printf "|%15s|\n",$1}'

|          Linux|

说明:字符串Linux被打印成一个占15 格、向右对齐的字符串,夹在两个竖杠之间,以
换行符结尾。

image.png

实战项目备份

cat 1| awk '/FFG/{printf"%s\t%s_TUMOR\n",$1,$2}'
image.png

awk处理“列”

参数
awk [option] 'BEGIN{初始代码} {循环代码} END{最后代码}' filename

运算符
|| 逻辑或
&& 逻辑与
~ ~! 匹配正则表达式和不匹配正则表达式

说明书

充分了解awk

第一: 自定义分隔符 -F

示例:

awk -F : '{print}' /etc/passwd
# 以冒号为分隔符,打印每行
awk -F : '{print $0}' /etc/passwd
# 等同于awk –F: '{print}' /etc/passwd
awk -F : '{print $1}'  /etc/passwd
# 以冒号为分隔符,打印每行的第一个字段
awk  -F : '{print "root"}' /etc/passwd
# 以冒号为分隔符,每行都打印root
awk -F : '{print $1"\t"$3}' /etc/passwd
# 以冒号为分隔符,打印每行的1、3字段,\t表示tab,默认时空格

第二: 理解 -v

-v var=value 自定义变量

awk -v test='hello gawk' '{print test}' /etc/fstab
# 这里自定义了test

第三:理解FS,OFS 和RS,ORS

FS 和 OFS 可以看做是字段分隔符
awk -v FS=':' '{print $1,FS,$3}' /etc/passwd
# 以冒号为输入字段分隔符,打印1、:、3字段
awk -v FS=':' -v OFS='-' '{print $1,$3,$7}' /etc/passwd
# 以冒号为输入字段分隔符,以----为输出字段分隔符,打印1、3、7字段

RS 和 ORS 可以看做是换行符
awk -v RS=' ' -v ORS='###' '{print$1,$2}' /etc/passwd
# 以空格为输入记录分隔符,以###为输出记录分隔符,打印每行
awk -v RS=' ' '{print$1,$2}' /etc/passwd
# 以空格为输入记录分隔符,碰到空格就换行,打印每行

awk实战代码

# 在gtf文件的第一列的N前加入ref| 
cat ref_GRCh38.p12_top_level.gff3 |grep -v '^#' |awk 'BEGIN{FS='\t';OFS='\t'}{gsub(/^N/,"ref|N",$1);print $0}' 
# 在gtf文件的第一列的最后加入| 
cat ref_GRCh38.p12_top_level.gff3_step1 |grep -v '^#' |awk 'BEGIN{FS='\t';OFS='\t'}{gsub(/$/,"|",$1);print $0}' 

打印除了第一行列的所有列

cat ref_GRCh38.p12_top_level.gff3 |head -50|grep -v '^#' |awk '{for(i=2;i<=NF;++i) printf $i "\t";printf "\n"}'

第五步整理好注释信息

zcat ref_GRCh38.p12_top_level.gff3.gz |grep -v '#'|cut -f 9|awk '/gene_biotype/{print $0}'|awk -F ';' '{for(i=1;i<=NF;i++){if($i ~/^gene_biotype=/){print $i}}}' |awk -F '=' '{print$2}'  >gene_type
## 找到有gene_biotype的行,并将这一行中的以gene_biotype=为开头的列找出来
zcat ref_GRCh38.p12_top_level.gff3.gz |grep -v '#'|cut -f 9|awk '/gene_biotype/{print $0}'|awk -F ';' '{for(i=1;i<=NF;i++){if($i ~/^gene=/){print $i}}}' |awk -F '=' '{print$2}'  >gene_name
paste gene_name gene_type >NCBI_ID_trans.txt

awk 玩转NCBI下载下来的gff文件

awk 包含

cat patient_info.txt |awk '/FFG/{printf "%s_tumor\t%s\n",$2,$4}' > tumor_config
cat patient_info.txt |awk '$0~"blood|BC"{printf "%s_normal\t%s\n",$2,$4}' > normal_config

常用代码

awk 有个类似的查找功能//

history |awk '/prefetch/{print $0}'
echo 1 2 3| awk '{ print "total pay for", $1, "is", $2 * $3 }'

awk -F #-F相当于内置变量FS, 指定分割字符

cat /etc/passwd |awk  -F ':'  '{print $1"\t"$7}' 
cat /etc/passwd |awk  -F ':'  'BEGIN {print "name,shell"}  {print $1","$7} END {print "blue,/bin/nosh"}'
awk '{count++;print $0;} END{print "user count is ", count}' /etc/passwd
awk -F ':' 'BEGIN {count=0;} {name[count] = $1;count++;}; END{for (i = 0; i < NR; i++) print i, name[i]}' /etc/passwd
awk '$3 == 0 { print $1 }' emp.data
awk '$3 >0 { print $1, $2 * $3 }' emp.data
awk '$3 > 15 { time = time + 1 } END{ print time, "s" }'
awk 'NF != 3     { print $0, "number of fields is not equal to 3" }'  # 与 && , 或 || , 以及非 !
awk '$2 < 3.35   { print $0, "rate is below minimum wage" }'  # Eg: !($2 < 4 && $3 < 20)
awk 'END { print NR, "employees" }'

awk     '{ pay = pay + $2 * $3 }
END { print NR, "employees"
      print "total pay is", pay
      print "average pay is", pay/NR
    }'

实战

将1-3,分别改为A-B

cat $1 |while read id 
do
    arr=(${id})
    pre_name=${arr[0]}
    after_name=${arr[1]}
    mv ${pre_name} $after_name
done

 bash chang_name.sh ./tmp
将1-3,分别改为A-B

查找

cat patient_info |awk '/FFG/{printf "%s_tumor\t%s\n",$2,$4}' > tumor_config
cat patient_info |awk '$0~"blood|BC"{printf "%s_normal\t%s\n",$2,$4}' > normal_config

awk

cat tumor_config |awk '{print$2}'|awk -F '_' 'BEGIN{FS='_';OFS='_'}{for(i=1;i<=(NF-2);i++){printf "%s_", $i}; printf "\n"}'
# 改进
cat tumor_config |awk '{print$2}'|awk -F '_' '{for(i=1;i<=(NF-2);i++){printf "%s_", $i}; printf "\n"}' |awk '{sub(/_$/,"")}1' >tumor_config_2

cat normal_config |awk '{print$2}'|awk -F '_' '{for(i=1;i<=(NF-2);i++){printf "%s_", $i}; printf "\n"}' |awk '{sub(/_$/,"")}1' >normal_config_2

这个时候printf 占主导,所有OFS 没有差别

删除最后一个字符
sed 's/.$//'
awk '{sub(/.$/,"")}1'
awk '{printf $0"\b \n"}' ufile

关于正则表达式的运用

目的删除红色部分

image.png
image.png
less colume1 |sed -r 's/_.*\.sort/\.sort/' 

.* 代表了任意字符

我自己傻傻的解决方式
# cat colume1 | awk '{gsub(/\_L4\_[a-z][0-9]/,".",$0);print$0}'
# cat colume1 |awk '{gsub(/_L4_*/,"",$0);print$0}'
# cat colume1|sed -r 's/\_L4\_*sort//g'
ls M* >colume1

cat colume1|awk -F '.sort' '{print$2}' >colume3
cat colume1|awk -F '.sort' '{print$1}' >colume2

cat colume2 |awk '{gsub(/\_L4\_....../,"",$0);print$0}' >colume4
# . 表示任意字符
paste colume4 colume3|awk '{printf"%s%s\n",$1,$2}' > final_colume
paste colume1 final_colume >config
vim rename.sh
cat $1| while read id 
do
    arr=($id)
    filename=${arr[0]}
    newfile=${arr[1]}
    mv $filename $newfile
done
bash rename.sh ./config

你可能感兴趣的:(Linux文本处理三架马车之二 awk)