shell awk 常用命令

在”a b c d”的b后面插入3个字段e f g

echo a b c d|awk '{$3="e f g "$3}1'

获取ipv4地址:

方法一:

ifconfig | awk '/inet / && !($2 ~/^127/){print $2}'

  方法二:

ifconfig | awk 'BEGIN{RS=""} !/^lo/{print $6}'

  方法三:

ifconfig | awk 'BEGIN{RS="";FS="\n"}!/lo/{$0=$2;FS=" ";$0=$0;print $2;FS="\n"}'

  读取ini中mysql 的配置文件:

[base]
name=os_repo
baseurl=https://xxx/centos/$releasever/os/$basearch
gpgcheck=0

enable=1

[mysql]
name=mysql_repo
baseurl=https://xxx/mysql-repo/yum/mysql-5.7-community/el/$releasever/$basearch

gpgcheck=0
enable=1

[epel]
name=epel_repo
baseurl=https://xxx/epel/$releasever/$basearch
gpgcheck=0
enable=1
[percona]
name=percona_repo
baseurl = https://xxx/percona/release/$releasever/RPMS/$basearch
enabled = 1
gpgcheck = 0

  

#/\[mysql\]/
awk '
index($0,"[mysql]"){
  print 
  while ( (getline var) >0){
    if(var ~ /\[.*\]/){
      exit
    }
    print var 
  }
}' 1.txt 

#getline返回值:
#>0:表示读取到数据
#=0:表示遇到结尾EOF,没有读取到东西
#<0: 表示读取报错

#按段读
awk 'BEGIN{RS=""}
   /\[mysql\]/{
     print;
     while((getline)>0){
       if(/\[.*\]/){
         exit
       }
       print
     }
   }' 1.txt

  去除重复的数据:

   awk -F "?" '{arr[$2]=arr[$2]+1;if(arr[$2]==1){print}}' 1.txt

   awk -F "?" '{arr[$2]++;if(arr[$2]==1){print}}' 1.txt

   awk -F "?" '!arr[$2]++' 1.txt

   awk -F "?" '!arr[$2]++{print}' 1.txt

  

2019-01-13_12:00_index?uid=123
2019-01-13_13:00_index?uid=123
2019-01-13_14:00_index?uid=333
2019-01-13_15:00_index?uid=9710
2019-01-14_12:00_index?uid=123
2019-01-14_13:00_index?uid=123
2019-01-15_14:00_index?uid=333
2019-01-16_15:00_index?uid=9710

  awk 次数统计

portmapper
portmapper
portmapper
portmapper
portmapper
portmapper
status
status
mountd
mountd
mountd
mountd
mountd
mountd
nfs
nfs
nfs_acl
nfs
nfs
nfs_acl
nlockmgr
nlockmgr
nlockmgr
nlockmgr
nlockmgr

  

awk '{arr[$0]++}END{for(i in arr){print arr[i],i}}' 1.txt

awk '{arr[$0]++}END{OFS="\t";for(idx in arr){print arr[idx],idx}}' 1.txt

 获取tcp连接: netstat -tnap

awk 统计TCP连接状态数量:

netstat -tnp | awk '/^tcp/{arr[$6]++}END{for(i in arr){print arr[i],i}}'

  

netstat -tnap | awk '/^tcp/{arr[$6]++}END{for(state in arr){print arr[state] ": " state}}'

  

netstat -tnap 2>/dev/null | awk '/^tcp/{arr[$6]++}END{for(state in arr){print arr[state] ": " state}}'

  

netstat -tna | /usr/bin/grep 'tcp' | awk '{print $6}' | sort | uniq -c

  统计日志中ip访问非200状态码的次数:

awk '$8!=200{arr[$1]++}END{PROCINFO["sorted_in"]="@val_num_desc";for(i in arr){if(cnt++==10){exit}print arr[i],i}}' access.log

  

awk '$8!=200{arr[$1]++}END{for(i in arr){print arr[i],i}}' access.log | sort -k1nr | head -n 10

  awk 统计独立Ip

url访问ip反问时间反问人

a.com.cn|202.109.134.23|2015-11-20 20:34:43|guest
b.com.cn|202.109.134.23|2015-11-20 20:34:48|guest
c.com.cn|202.109.134.24|2015-11-20 20:34:48|guest
a.com.cn|202.109.134.23|2015-11-20 20:34:43|guest
a.com.cn|202.109.134.24|2015-11-20 20:34:43|guest
b.com.cn|202.109.134.25|2015-11-20 20:34:48|guest

  

BEGIN{
  FS="|"
}
{
if(!arr[$1,$2]++){
  arr1[$1]++
}
}
END{
  for(i in arr1){
    print i,arr1[i] >(i".txt")
  }
}

  

BEGIN{
  FS="|"
}
!arr[$1,$2]++{
  arr1[$1]++
}
END{
   for(i in arr1){
    print i,arr1[i] >(i".txt")
  }
}

  执行:

awk -f 1.awk 1.txt

  awk处理字段缺失的数据:

ID  name    gender  age  email          phone
1   Bob     male    28   abc@qq.com     18023394012
2   Alice   female  24   def@gmail.com  18084925203
3   Tony    male    21                  17048792503
4   Kevin   male    21   bbb@189.com    17023929033
5   Alex    male    18   ccc@xyz.com    18185904230
6   Andy    female       ddd@139.com    18923902352
7   Jerry   female  25   exdsa@189.com  18785234906
8   Peter   male    20   bax@qq.com     17729348758
9   Steven          23   bc@sohu.com    15947893212
10  Bruce   female  27   bcbd@139.com   13942943905

  gawk为了解决这种特殊需求,提供了FIELDWIDTHS变量。

awk '{print $4}' FIELDWIDTHS="2 2:6 2:6 2:3 2:13 2:11" a.txt

  

BEGIN{
   FIELDWIDTHS="2 2:6 2:6 2:3 2:13 2:11"
}
{
  print $0
}

  awk 处理字段中包含了字段分隔符的数据

Robbins,Arnold,"1234 A Pretty Street, NE",MyTown,MyState,12345-6789,USA

  需求:取得第三个字段”1234 A Pretty Street, NE”

FPAT可以收集正则匹配的结果,并将它们保存在各个字段中。(就像grep匹配成功的部分会加颜色显示,而使用FPAT划分字段,则是将匹配成功的部分保存在字段$1 $2 $3...中)。

echo 'Robbins,Arnold,"1234 A Pretty Street, NE",MyTown,MyState,12345-6789,USA' |\
awk 'BEGIN{FPAT="[^,]+|\".*\""}{print $1,$3}'

  方法2:

BEGIN{
  FPAT="[^,]+|\".*\""
}
{
  print $1,$3
}

  

awk -f 1.awk 1.txt

  awk 取字段中指定字符数量

16  001agdcdafasd
16  002agdcxxxxxx
23  001adfadfahoh
23  001fsdadggggg

  

awk '{print $1,substr($2,1,3)}' 1.txt

  

awk '{print $1,$2}' FIELDWIDTH="2 2:3" 1.txt
awk 'BEGIN{FIELDWIDTH="2 2:3"}{print $1,$2}' 1.txt

  awk 行转列

name age
alice 21
ryan 30

  

{
  for(i=1;i<=NF;i++){
    if(i in arr){
      arr[i]=arr[i]" "$i
    }else{
      arr[i]=$i
    }
  }
}

END{
  for(i=1;i<=NF;i++){
    print arr[i]
  }
}

  awk 筛选给定是时间范围内的日志

grep/sed/awk用正则去筛选日志时,如果要精确到小时、分钟、秒,则非常难以实现

但是awk提供了mktime()函数,它可以将时间转换成epoch时间值

# 2019-11-10 03:42:40转换成epoch
$ awk 'BEGIN{print mktime("2019 11 10 03 42 40")}'
1573328560

  可以取得日志中的时间字符串部分,再将它们的年、月、日、时、分、秒都取出来,然后放入mktime()构建成对应的epoch值。因为epoch值是数值,所以可以比较大小,从而决定时间的大小

strptime1()实现的是将2019-11-10T03:42:40+08:00格式的字符串转换成epoch值,然后和which_time比较大小即可筛选出精确到秒的日志

BEGIN{
  str="2019-11-10T20:25:39+08:00"
  #strptime(str) 筛选什么时间的日志,将其构建成epoch 值
  which_time=mktime("2019 11 10 03 42 40")
}

{
  #去除日志中的日期时间字符串部分
  match($0,"^.*\\[(.*)\\].*",arr)
  #将日期时间字符串转换成eposh值
  tmp_time=strptime(arr[1])
  #通过比较epoch值来比较时间
  if(tmp_time>which_time){
    print
  }
}

function strptime (str   ,arr,Y,M,D,H,m,S)
{
  patsplit(str,arr,"[0-9]{1,4}")
  Y=arr[1]
  M=arr[2]
  D=arr[3]
  H=arr[4]
  m=arr[5]
  S=arr[6]
  return mktime(sprintf("%s %s %s %s %s %s",Y,M,D,H,m,S))
}

  

strptime2()实现的是将10/Nov/2019:23:53:44+08:00格式的字符串转换成epoch值,然后和which_time比较大小即可筛选出精确到秒的日志。

BEGIN{
  # 要筛选什么时间的日志,将其时间构建成epoch值
  which_time = mktime("2019 11 10 03 42 40")
}

{
  # 取出日志中的日期时间字符串部分
  match($0,"^.*\\[(.*)\\].*",arr)
  
  # 将日期时间字符串转换为epoch值
  tmp_time = strptime2(arr[1])
  
  # 通过比较epoch值来比较时间大小
  if(tmp_time > which_time){
    print 
  }
}

# 构建的时间字符串格式为:"10/Nov/2019:23:53:44+08:00"
function strptime2(str   ,dt_str,arr,Y,M,D,H,m,S) {
  dt_str = gensub("[/:+]"," ","g",str)
  # dt_sr = "10 Nov 2019 23 53 44 08 00"
  split(dt_str,arr," ")
  Y=arr[3]
  M=mon_map(arr[2])
  D=arr[1]
  H=arr[4]
  m=arr[5]
  S=arr[6]
  return mktime(sprintf("%s %s %s %s %s %s",Y,M,D,H,m,S))
}

function mon_map(str   ,mons){
  mons["Jan"]=1
  mons["Feb"]=2
  mons["Mar"]=3
  mons["Apr"]=4
  mons["May"]=5
  mons["Jun"]=6
  mons["Jul"]=7
  mons["Aug"]=8
  mons["Sep"]=9
  mons["Oct"]=10
  mons["Nov"]=11
  mons["Dec"]=12
  return mons[str]
}

  awk去除/**/之间的内容

文档:

/*AAAAAAAAAA*/
1111
222

/*aaaaaaaaa*/
32323
12341234
12134 /*bbbbbbbbbb*/ 132412

14534122
/*
    cccccccccc
*/
xxxxxx /*ddddddddddd
    cccccccccc
    eeeeeee
*/ yyyyyyyy
5642341

  两种实现方式:

/\/\*/{
  #同行有*/
  if(/\*\//){
    print gensub("(.*)/\\*.*\\*/(.*)","\\1\\2","g",$0)
  }else{
    #同行没有“*/”
    # 1.去掉/*行后面的内容
    print gensub("(.*)/\\*.*","\\1","g",$0)

    #2.继续读取,直到出现*/,并去掉中间的所有数据
    while((getline)>0){
       if(/\*\//){
         print gensub(".*\\*/(.*)","\\1","g",$0)
       }
    }
  }
}
#非注释内容
!/\/\*/{print}



index($0,"/*"){
  #如果*/在同行
  if(index($0,"*/")){
    print gensub("^(.*)/\\*.*\\*/(.*)$","\\1\\2","g",$0)
  }else{
    #*/不同行
    #输出/*前面的内容
    print gensub("^(.*)/\\*.*","\\1","g",$0)

    #继续读取,直到遇到*/结束符
    while((getline var)>0){
      if(index(var,"*/")){
        print gensub("^.*\\*/(.*)","\\1","g",var)
        break 
      }
    }
  }  
}

!index($0,"/*"){
  print
}

  从如下类型的文件中,找出false段的前一段为i-order的段,同时输出这两段

2019-09-12 07:16:27 [-][
  'data' => [
    'http://192.168.100.20:2800/api/payment/i-order',
  ],
]
2019-09-12 07:16:27 [-][
  'data' => [
    false,
  ],
]
2019-09-21 07:16:27 [-][
  'data' => [
    'http://192.168.100.20:2800/api/payment/i-order',
  ],
]
2019-09-21 07:16:27 [-][
  'data' => [
    'http://192.168.100.20:2800/api/payment/i-user',
  ],
]
2019-09-17 18:34:37 [-][
  'data' => [
    false,
  ],
]

  方法1:

BEGIN{
  RS="]\n"
  ORS=RS
}
{
  if($0 ~ /false/ && prev ~ /i-order/){
    print prev
    print $0
  }
  prev=$0
}

  

grep -Pz '(?s)\d+((?!2019).)*i-order(?1)+\d+(?1)+false(?1)+' 

  





 

posted @ 2021-01-05 13:27  石shi  阅读(253)  评论(0编辑  收藏  举报