• 【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
    
    • 1
    • 2
    • 3
    • 4

    以上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
    
    • 1

    也可用sed实现:

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

    需求2: 格式化输出

    代码2:

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

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

    使用int直接输出整型:

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

    需求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"的行
    
    • 1
    • 2
    • 3

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

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

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

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

    使用正则匹配:

    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"的行
    
    • 1
    • 2
    • 3

    正则匹配:

    表达式字符说明
    ~匹配表达式
    !~不匹配表达式
    [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
    
    • 1

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

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

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

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

    需求4:计算某列的和

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

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


    需求5:大小写转换

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

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

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

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

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

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

    解释:输入文件以"\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
    
    • 1
    • 2

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

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

    需求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' 
    
    • 1

    需求10:单引号转义

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

    附1:

    附2:sed一些常用命令

    增:

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

    删:

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

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

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

    改(替换):

    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不对
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

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

    输出/查:

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

    未完待续。。。

  • 相关阅读:
    Redis从入门到精通(二:数据类型)
    .NET下数据库的负载均衡(有趣实验)(续)
    php 日期
    【Element-UI】Mock.js,案例首页导航、左侧菜单
    羧基功能化咪唑基离子液体[CEBIM][PF6]改性普鲁士兰多糖的反应合成
    jar解压修改后,如果再打成jar包
    Go基础17-明确哪些函数可以作为deferred函数?
    mongodb搭建副本集
    React 状态管理 - Context API 前世今生(下)
    Android定时相关
  • 原文地址:https://blog.csdn.net/sinat_32872729/article/details/127569919