Skip to content

Text Swordsman

awk

基本语法

bash
awk [POSIX or GNU style options] -f progfile [--] file 
POSIX options:          GNU long options: (standard)
        -f progfile             --file=progfile
        -F fs                   --field-separator=fs
        -v var=val              --assign=var=val
        
-F fs          # fs指定输入分隔符,fs 可以是字符串或正则表达式,如-F:
-v var=val     # 赋值一个用户定义变量,将外部变量传递给awk
-f progfile    # 从脚本文件中读取awk命令


# example 
awk -F':' '{print $1}' /etc/passwd
awk 'BEGIN { print "Don\47t Panic!" }'


# 运行 awk 程序,打印每行输入流的第一列
awk '{print $1}'


# awk 文件方式执行
cat > demo.awk << "EOF"
#! /bin/awk -f
BEGIN { print "Don't Panic!" }
EOF
# 运行
awk -f demo.awk top.txt
chmod +x demo.awk && ./demo.awk

变量

变量说明
ARGC命令行参数数量
ARGIND命令行中当前文件的位置(从0开始算)
ARGV包含命令行参数的数组
CONVFMT数字转换格式(默认值为%.6g)
ENVIRON环境变量关联数组
ERRNO最后一个系统错误的描述
FIELDWIDTHS字段宽度列表(用空格键分隔)
FILENAME当前输入文件的名称
FNR同NR,但相对于当前文件
FS字段分隔符(默认是任何空格)
IGNORECASE如果为真,则进行忽略大小写的匹配
NF表示字段数,在执行过程中对应于当前的字段数
NR表示记录数,在执行过程中对应于当前的行号
FILENAME当前输入文件的名
OFMT数字的输出格式(默认值是%.6g)
OFS输出字段分隔符(默认值是一个空格)
ORS输出记录分隔符(默认值是一个换行符)
RS记录分隔符(默认是一个换行符)
RSTART由match函数所匹配的字符串的第一个位置
RLENGTH由match函数所匹配的字符串的长度
SUBSEP当前输入文件的名
FILENAME数组下标分隔符(默认值是34)

函数 && 条件

bash
# 常用函数
# tolower():字符转为小写。
# length():返回字符串长度。
# substr():返回子字符串。
# sin():正弦。
# cos():余弦。
# sqrt():平方根。
# rand():随机数。

# 转换大写示例
awk -F ':' '{ print toupper($1) }' /etc/passwd


# if 条件语句
awk -F ':' '{if ($1 > "m") print $1; else print "---"}' /etc/passwd

常用用法

bash
awk 'BEGIN{ commands } pattern{ commands } END{ commands }'
首先执行 BEGIN 语句块,只会执行一次。通常用于变量初始化,头行打印一些表头信息,在通过stdin读入数据前就被执行。
每读取一行数据使用 pattern{ commands }循环处理数据。
最后执行 END 语句块,只会执行一次,通常用于统计结果。

# example
cat /etc/passwd |awk  -F ':'  'BEGIN {print "name,shell"}  {print $1","$7} END {print "blue,/bin/nosh"}'


# file 
tee top.txt << "EOF"
    PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
 213123 root      20   0    9584   4060   3344 R   6.2   0.1   0:00.01  top
1275702 tomcat    20   0    999    30596  13976 S  6.2   0.4 741:21.61  metrics
1612431 systemd   20   0    888    7708 103788 S   6.2   9.6   2519:09  k3s
      1 systemd   20   0    777    1884   6596 S   0.0   0.1  43:55.21  systemd
EOF

# 格式化输出
# - 左对齐
# %s 字符串
# %d 十进制有符号整数
# %u 十进制无符号整数
awk '{printf "%-8s %-8s %-8s %-18s\n",NR, $1,$2,$12}' top.txt

# 计算结果
awk 'BEGIN {sum=0} {printf "%-8s %-8s %-18s\n", $1, $9, $11; sum+=$9} END {print "cpu sum:"sum}' top.txt

# 外部引用变量
awk -v sum=0 '{printf "%-8s %-8s %-18s\n", $1, $9, $11; sum+=$9} END {print "cpu sum:"sum}' top.txt 

# 筛选
awk 'NR>1 && $9>0 {printf "%-8s %-8s %-18s\n",$1,$9,$12}' top.txt 
awk 'NR==1 || $2~/tomcat/ {printf "%-8s %-8s %-8s %-18s\n",$1,$2,$9,$12}' top.txt

# action 块筛选
awk '{if($9>0){printf "%-8s %-8s %-8s %-18s\n",$1,$2,$9,$12}}' top.txt

# 数组计算第二列的用户进程数量
awk 'NR!=1{a[$2]++;} END {for (i in a) print i ", " a[i];}' top.txt


# 数组操作
# 获取长度
awk 'BEGIN{info="it is a test";lens=split(info,tA," ");print length(tA),lens;}'
# 循环输出,下标从1开始
awk 'BEGIN{info="it is a test";split(info,tA," ");for(k in tA){print k,tA[k];}}'
awk 'BEGIN{info="it is a test";tlen=split(info,tA," ");for(k=1;k<=tlen;k++){print k,tA[k];tlen;}}'
# 判断 key in array(判断语法为 key in array)
awk 'BEGIN{tB["a"]="a1";tB["b"]="b1";if("c" in tB){print "ok";};for(k in tB){print k,tB[k];}}'
# 删除 key
awk 'BEGIN{tB["a"]="a1";tB["b"]="b1";delete tB["a"];for(k in tB){print k,tB[k];}}'


# 判断字符拆分输出文件
awk 'NR>1 {if($0~/tomcat/){printf "%-8s %-8s %-8s %-18s\n",$1,$2,$9,$12 > "1.txt"}else if($0~/root/){printf "%-8s %-8s %-8s %-18s\n",$1,$2,$9,$12 > "2.txt"}else{printf "%-8s %-8s %-8s %-18s\n",$1,$2,$9,$12 > "3.txt"}}' top.txt 


# 删除关键字 memory 的重复行
awk '!seen[$0]++ || !/memory/' values.yaml
# 删除并修改原文件
awk '!seen[$0]++ || !/memory/' values.yaml > tmp && mv -v tmp values.yaml


# 替换 ORS, 去除换行符
awk 'BEGIN{ORS=""};{print $0}' x.txt

grep

基本语法

bash

常用用法

bash

sed

基本语法

bash
sed [OPTION]... {script-only-if-no-other-script} [input-file]...

# options
  -n, --quiet, --silent
  -e script, --expression=script
  -f script-file, --file=script-file
  -E, -r, --regexp-extended
  -i[SUFFIX] edit files in place (makes backup if SUFFIX supplied)

# action
a\:追加行,a\的后面跟上字符串s(多行字符串可以用\n分隔),则会在当前选择的行的后面都加上字符串s
c\:替换行,c\后面跟上字符串s(多行字符串可以用\n分隔),则会将当前选中的行替换成字符串s
i\:插入行,i\后面跟上字符串s(多行字符串可以用\n分隔),则会在当前选中的行的前面都插入字符串s
d:删除行,该命令会将当前选中的行删除
p:打印,该命令会打印当前选择的行到屏幕上
y:替换字符,用法:y/Source-chars/Dest-chars/,分割字符/可以用任意单字符代替,用Dest-chars中对应位置的字符替换掉Soutce-chars中对应位置的字符
s:替换字符串,用法:s/Regexp/Replacement/Flags,分隔字符/可以用其他任意单字符代替,用Replacement替换掉匹配字符串

# flags
g:将用Replacement替换模版空间中所有匹配Regexp的部分,则不仅仅是第一个匹配部分
digit:只用Replacement替换模版空间中第digit(digit是1至9)个匹配Regexp的部分
p:若发生了替换操作,指示显示模版空间中新的数据
w file-name:若发生了替换操作,指示将模版空间中新的数据写入指定的文件file-name中
i:表示进行Regexp匹配时,是不区分大小写字母的


# example 
sed -e 's/tomcat/fff/' -e 's/root/xxx/' top.txt

# insert or append new line
nl top.txt | sed '2i newline'
nl top.txt | sed '2a newline'
# delete line
nl top.txt | sed '2,3d'
nl top.txt | sed '3,$d'
# change and print
nl top.txt | sed '2c new content'
nl top.txt | sed -n '2,3p'

# search and delete
nl top.txt | sed '/tomcat/d' top.txt
# search and execute
nl top.txt | sed -n '/tomcat/{s/tomcat/xxx/;p}' 

# replace and print
sed -p 's/tomcat/fff/p' top.txt
# regex replace 
sed -r 's/xxx[[::space::]]/root/' top.txt


# replace files and backup to top.txt_bk_xxx
sed -i_bk_xx 's/tomcat/fff/p' top.txt

常用用法

bash
# file 
tee top.txt << "EOF"
    PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
 213123 root      20   0    9584   4060   3344 R   6.2   0.1   0:00.01  top
1275702 tomcat    20   0    999    30596  13976 S  6.2   0.4 741:21.61  metrics
1612431 systemd   20   0    888    7708 103788 S   6.2   9.6   2519:09  k3s
      1 systemd   20   0    777    1884   6596 S   0.0   0.1  43:55.21  systemd
EOF

# search and append new line
sed -n '/requests/a\  cpu: 1000m\n  memory: 1Gi' values.yaml

# search and replace next line
sed -i '/autoscaling:/{n;s/enabled: true/enabled: false/}' values.yaml
  1. gawk official
  2. sed official