【linux】awk常用处理文件命令示例-替换/格式化/条件选择/求和/正则/子字符串

一个示例文件myfile.txt:(Tab分割:“\t”)

head1head2head3head4head5
aaabbbAAccddCCABCD10
XaabbbAYccddCCAbCD22
aXaXbbAAycddZCABcD35
aaXbXXAAcyddCZABCd199

需求1: 将第1列替换字符中的X都替换为A

awk '{gsub(/X/,"A",$1); print}' myfile.txt
awk '{gsub(/X/,"A",$1); print $0}' myfile.txt
awk -F"\t" '{OFS="\t"}{gsub(/X/,"A",$1); print $0}' myfile.txt
awk '{FS="\t"; OFS="\t"}{gsub(/X/,"A",$1); print $0}' myfile.txt

以上4个命令是等价的。

代码1: 解释命令参数

命令/参数说明
$0/$1awk基本命令,获取所有列;$1: 获取第一列,$2: 获取第二列,$3: … 。
gsub使用gsub函数对字符(串)替换。gsub函数参数
gsub(/原字符(串)正则表达式/, 修改字符(串), [指定列,默认所有列])
-F/FS指定输入的列分割字符,默认是空白字符。示例代码指定Tab “\t”。
注意,如果自定义指定了输入列的分隔符,默认的输出分割符是一个空格
如输出列还按tab分割,需要指定OFS
OFS输出的列分割符。
print默认print的是所有列,也可使用$0,$1,…指定输出的列。

生成结果:

head1head2head3head4head5
aaabbbAAccddCCABCD10
AaabbbAYccddCCAbCD22
aAaAbbAAycddZCABcD35
aaAbAAAAcyddCZABCd199

例:去除bed文件中的chr字符

awk '{ gsub(/chr/,""); print $1"\t"$2"\t"$3 }' test.bed

也可用sed实现:

sed 's/^chr//g' test.bed

需求2: 格式化输出

代码2:

awk '{printf ("%-30s\t%.10f\t%.4f\n",$1,$5*2,$2/10}') myfile.txt

解释:第一个逗号,之前为指定的格式,之后为对应格式的值。该示例输出为:原文件第一列【格式为30个字符宽度】,TAB分割,原文件第5列乘2【格式为保留10位小数】,TAB分割,原文件第2列除以10【格式为保留4位小数】。

使用int直接输出整型:

awk '{print int($1)}' myfile.txt

需求3:条件输出if

awk '{if(NR==3){print $0}}' myfile.txt  # 输出文件第3行
awk '{if($2>=1){print}}' myfile.txt  # 输出文件"第2列值>=1"的行
awk '{if($5=="ABC")print}' myfile.txt  # 输出文件第3列字符为"ABC"的行

awk根据条件,也可不使用print默认输出整行,更简洁:

awk 'NR==3' myfile.txt  # 输出文件第3行
awk '$2>=1' myfile.txt  # 输出文件"第2列值>=1"的行
awk '$5=="ABC"' myfile.txt  # 输出文件第3列字符为"ABC"的行

使用或||和且&&条件判断:

awk '$1=="aa" || $3=="bb"' myfile.txt  # 第1列为'aa'或第3列'bb'的行 
awk '$1!="aa" && $3!="bb"' myfile.txt  # 第1列不等于'aa'且第3列不等于'bb'时的行

使用正则匹配:

awk '{if($1~/^AB/)print}' myfile.txt  # 输出第1列开头是"AB"的行
awk '{if($1~/AB$/)print}' myfile.txt  # 输出第1列末尾是"AB"的行
awk '{if($1~/^AB$/)print}' myfile.txt  # 第1列开头和末尾之间是"AB",相当于输出第1列等于"AB"的行

正则匹配:

表达式字符说明
~匹配表达式
!~不匹配表达式
[0-9]匹配0~9数字
+匹配一个或多个
?匹配0个或1个,比如,匹配第1列是0-99M: $1~/[0-9]?[0-9]M/
|匹配或,比如,匹配第1列的9M或10M: $1~/9M|10M/
awk '{if($6!~/^[0-9]+M$/)print}' myfile.txt  # 匹配第6列是"数值M"的格式,例如:100M, 120M, 80M

例:输出fastq文件中的序列行,取余%

awk '{if(NR%4==2){print}}' yourfq  # 每4行为一组,只输出第2行

用sed同理实现获取指定行:

# 同 sed -n
sed -n '3p' myfile.txt  # 输出第三行

需求4:计算某列的和

awk '{sum += $3}END{print sum}' myfile.txt

解释:将第3列累加,END是指最后执行的命令,即在累加后在最后输出累加的值sum。


需求5:大小写转换

awk '{print toupper($1)}' myfile.txt  # 第1列转大写
awk '{print tolower($1)}' myfile.txt  # 第1列转小写

需求6:获取子字符串;根据长度获取子字符串

awk '{print substr($1,5,2)}'  myfile.txt  # (1) 取子字符串
awk '{print substr($1,1,length($1)-3)}' file  # (2) 根据字符长度取子字符串

(1) 解释:取第一列,从第5位开始,往后取2个字符。
(2) 解释:取第一列,从第1位开始,往后取第1列总长度-3个字符。

需求7:根据指定字符对某列进行分割

awk -F "\t" '{OFS="\t"}{split($1, spA, ":"); print spA[2]}' myfile.txt

解释:输入文件以"\t"分割、输出也是"\t"。对第1列按冒号:分割,定义分割后的列表为spA,输出spA[2]即冒号分割的第2列。比如如下文件,":"分割第一列输出的第二个为b1, b2。

head1head2head3
aa:b1:ccx1:yy:zzabcdef
aa:b2:ccx2:yy:zzabcdef

需求8:传入变量

x1=ABC  # 外部定义的变量
awk -v localx1="${x1}" {print localx1"\t"$1}  myfile.txt

使用 -v参数增加变量,如果有多个变量,使用多个-v即可:

x1=ABC
x2=EFG
awk -v localx1="${x1}" -v2 localx2=${x2} {print $1"\t"localx1"\t"localx2}  myfile.txt

需求9:文件格式转置

awk '{i=1; while(i<=NF){col[i]=col[i] $i "\t";i=i+1}}END{i=1;while(i<=NF){print col[i];i=i+1}}' myfile.txt | sed 's/[ \t]*$//g' 

需求10:单引号转义

awk '{print "'\''"}'  myfile.txt

附1:

附2:sed一些常用命令

增:

sed '1s/^/str1\t&/' file  # file第一行行开始位置增加字符'str1'
sed '1i aAaaAa' test_sed.txt # 第一行之前增加一行(i表示增加指定行前)
sed '$a aAaaAa' test_sed.txt # 末尾行之后增加一行(a表示增加指定行后)

删:

sed '5d' filename  # 删除第5行
sed '$d' filename  # 删除最后一行
sed '1,5d' filename  # 删除从第1行到第5行
sed '/^\s*$/d' filename  # 删除空行

注: 连续使用sed,行号是否改变,eg:

sed '2,5d' file | sed '3s/str1/str2/'   # 删除第2,5行,替换原始文件的第3行,而不是删除后文件的第3行

改(替换):

sed '1s/str1/str2/' filename  # 第一行(1s)第一个str1替换为str2(标准输出)
sed '1s/str1/str2/g' filename  # 第一行(1s)所有str1替换为str2(标准输出)
sed 's/str1/str2/' filename  # 每行第一个str1替换为str2(标准输出)
sed 's/str1/str2/g' filename # 所有行所有str1替换为str2
sed 's/\t/str2/g' filename  # 把\t(Tab空格)换为str2
sed -i '1s/abc/defg/g' filename  # 直接替换源文件内容
sed '1s/^/#&/' # 第一行开头加'#' (用于注释命令行)

# 替换中有路径:
sed "2s/\/aaa\/bbb.txt/\/ccc\/ddd.txt/" filename  # 替换中含有路径需使用双引号
sed "2s#/aaa/bbb.txt#/ccc/ddd.txt#g"  filename  # 有包含路径符合"/",使用"#"更方便

sed '2,5s/s1/s2/' filename # 相邻多行替换,从第2到第5行。
# 不相邻的多个行如何替换?  sed "1s;3,5s/^/xxx\t/g" filename不对

注:如果替换字符使用变量:变量需要加引号

输出/查:

sed -n '1,3p' filename  # 输出第一到第三行内容
sed -n '1p;3p' filename  # 输出第一行和第三行内容
sed -n '15,$p' filename  # 输出第15行到最后一行的内容
sed -n "1,3p;5p" filename  # 输出第一到第三行内容、第5行

未完待续。。。

  • 4
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值