Linux命令_awk & 字符串过滤

发布于:2023-02-06 ⋅ 阅读:(928) ⋅ 点赞:(0)

前言

被称为 Linux 文本操作三剑客之一的 awk 不但可以处理复杂文件输出,更是一门编程语言。支持对文本每行每列精确读出、格式化输出、正则匹配、if 判断、数组、循环。

目录

1. 语法

1.1. 选项参数

1.2. 内置变量

1.3. 运算符

2. 参数示例

2.1. 示例选项参数:-F

2.2. 示例选项参数:-v

2.3. 示例选项参数:-f

3. 常见用法

3.1. 匹配行

3.1.1. 匹配第1行

3.1.2. 匹配最后1行

3.1.3. 匹配大于第1行的全部行

3.1.4. 匹配6-8行

3.1.5. 输出匹配行的下1行

3.1.6. 打印行号

3.1.7. 模糊匹配行

3.1.8. 范围匹配字符串

3.1.9. 逻辑匹配

3.1.10. 忽略大小写

3.2. 匹配列

3.2.1. 匹配第一列

3.2.2. 匹配最后一列

3.2.3. 匹配倒数第二列

3.2.4. 匹配第2列和第5列

3.2.5. 匹配第3列到第五列

3.2.6. 精确匹配某一列

3.2.7. 模糊匹配某一列

3.3. BEGIN / END使用

3.3.1. 开始前输出字符串

3.3.2. 结束后输出字符串

4. 正则表达式

5. 数学运算

6. IF判断

7. 循环语句

7.1. while 循环

7.2. for 循环

7.3. 跳出循环

8. awk 内置函数

8.1. 生成随机数

8.2. 时间戳转换

8.3. 文件比较

9. 文本三剑客其他命令


1. 语法

awk  [参数选项]  [条件筛选]  文件名

1.1. 选项参数

-F:指定分隔符
-v:设置变量
-f:从脚本文件中读取awk命令

1.2. 内置变量

$n :n用数字代替,表示匹配第n列
$0 :匹配全部列
NR :输出每行行号
NF :输出每行字段数
$NF:输出最后一列
$(NF - 1):输出倒数第二列

1.3. 运算符

**************** 逻辑类 ****************
&&:逻辑匹配-与
||:逻辑匹配-或
! :逻辑匹配-非
~ :匹配正则表达式
!~:正则表达式取反

**************** 运算类 ****************
+ :加
- :减
* :乘
/ :除
% :取余
^ :幂
> :大于
< :小于
==:等于
!=:不等于
>=:大于等于
<=:小于等于

2. 参数示例

2.1. 示例选项参数:-F

awk -F '|' '{print $1}' file.txt
awk -F '2' '{print $1}' file.txt

awk -F '[|,:]' file        # 指定多个分隔符

2.2. 示例选项参数:-v

awk -v 'num=1' '{print $1 + num}' file.txt

a=10

awk -v "b=$a" 'BEGIN{print b}'

2.3. 示例选项参数:-f

3. 常见用法

3.1. 匹配行

3.1.1. 匹配第1行

awk 'NR == 1' file.txt    # NR等于1匹配第一行,等于2匹配第二行

3.1.2. 匹配最后1行

awk 'END{print $0}' file.txt

3.1.3. 匹配大于第1行的全部行

awk '$NR > 1' file.txt    # 使用运算符,>、<、= 皆可通用

3.1.4. 匹配6-8行

awk 'NR>=6 && NR<=8' file.txt    # 使用逻辑符进行匹配

3.1.5. 输出匹配行的下1行

seq 1 10 |awk '/3/ {getline; print}'

输出匹配行 + 下1行

seq 1 10 |awk '/3/ {print; getline; print}' 

3.1.6. 打印行号

awk '{print NR}' file.txt        # 只打印行号
awk '{print NR, $0}' file.txt    # 输出所有列,并在最前面输出行号
awk 'END{print NR}' file.txt     # 输出最后一行的行号,可以理解为总行数

3.1.7. 模糊匹配行

seq 1 10 |awk '/3/ {print $0}'    # 匹配包含3的行

3.1.8. 范围匹配字符串

使用逗号分割,/b/ 表示开始行,/d/表示结束行,取中间范围
echo -e " a \n b \n c \n d" |awk '/b/, /d/'

3.1.9. 逻辑匹配

&& 匹配,匹配包含a且包含b的行
echo -e "abc \n def" |awk '/a/ && /b/ {print $0}'

|| 匹配,匹配包含a或者包含e的行
echo -e "abc \n def" |awk '/a/ || /e/ {print $0}'

!取反,不匹配包含a的行
echo -e "abc \n def" |awk '! /a/ {print $0}'

 

3.1.10. 忽略大小写

IGNORECASE=1 表示忽略大小写
echo -e " a \n A \n b \n c" |awk 'BEGIN{IGNORECASE=1} /a/'

3.2. 匹配列

3.2.1. 匹配第一列

awk '{print $1}' file.txt    # $0匹配全部列,$1匹配第一列,$2匹配第二列

3.2.2. 匹配最后一列

awk '{print $NF}' file.txt

不匹配最后一列

echo "a b c d"  |awk '{$NF=""; print $0}'

3.2.3. 匹配倒数第二列

awk '{print $(NF - 1)}' file.txt    # NF - 1 表示倒数第二列,NF - 2 表示倒数第三列

不匹配倒数第2列

echo "a b c d" |awk '{$(NF-1)=""; print $0}'

不匹配倒数第2列和最后1列

echo "a b c d" |awk '{$NF=""; $(NF-1)=""; print $0}'

3.2.4. 匹配第2列和第5列

awk '{print $2, $5}' file.txt    # 指定匹配多少列,增加 $n 即可
awk '{print $2 $5}' file.txt     # 去除逗号,表示去除分割输出第2列和第5列

3.2.5. 匹配第3列到第五列

awk '{for (i=3; i<=5; i++) print $i}' file.txt     # 匹配第3列到第5列
awk '{for (i=3; i<=NF; i++) print $i}' file.txt    # 匹配第3列到最后一列(纵向输出)
awk '{for (i=3; i<=NF; i++) {printf "%s ", $i}}' file.txt    # 横向输出

3.2.6. 精确匹配某一列

awk '/^a/' file.txt        # 匹配以 a 开头的列
awk '/c$/' file.txt        # 匹配以 c 结尾的列
awk '$1 == "a"' file.txt    # 匹配第1列等于 a 的行,$1 表示第一列,那么$2等于第二列

3.2.7. 模糊匹配某一列

awk '$1 ~ "a"' file.txt    # 匹配第一列存在 a 的行,$1等于第一列,那么$2等于第2列

匹配第1列包含a或b

awk '$1 ~ /[ab]/ file.txt

匹配第1列不包含a或b

awk '$1 !~ /[ab]/ file.txt

3.3. BEGIN / END使用

  • BEGIN:在处理文件之前执行该操作
  • END:在处理文件之后执行该操作

3.3.1. 开始前输出字符串

seq 1 3 |awk 'BEGIN{print "--- start ---"} {print $0}'

3.3.2. 结束后输出字符串

seq 1 3 |awk '{print $0} END{print "--- stop ---"}'

4. 正则表达式

字符 解释 用法
^ 匹配以什么开始 awk '/^ab/p' 匹配以ab开头的行
$ 匹配以什么结尾 awk '/ab$/p' 匹配以ab结尾的行
. 匹配任意一个字符 awk '/a.c/p'  只匹配a与c之间拥有一个字符的行
.+ 匹配1次或多次 awk '/a.+c/p' 匹配a与c之间任意字符的行,不包含ac
* 匹配0次或多次 awk '/a*c/p'  匹配a与c之间任意字符的行,包含ac
| 相当于 or awk '/ab|ac/p' 匹配包含ab或ac的行
[] 匹配括号中任意一个字符 awk '/[ac]/p'   匹配包含a或c的行
[^] 匹配非括号中任意一个字符 awk '/[^ac]/p' 匹配不包含a或c的行
- [0-9] 匹配数字 awk '/[0-9]/p' 匹配包含数字的行
[^0-9] 匹配非数字 awk '/[^0-9]/p' 匹配不包含数字的行
[a-z] 匹配小写字符串 awk '/[a-z]/p' 匹配包含小写字符串的行
[^a-z] 匹配非小写字符串 awk '/[^a-z]/p' 匹配不包含小写字符串的行
[A-Z] 匹配大写字符串 awk '/[A-Z]/p' 匹配包含大写字符串的行
[^A-Z] 匹配非大写字符串 awk '/[^A-Z]/p' 匹配不包含大写字符串的行
() (a|b) 匹配括号中任意字符 awk '/0(a|b)1/p' 只匹配0a1和0b1的行
(a)+ 匹配包含1个或多个a awk '/0(a)+1/p' 匹配0和1之前1个或多个a,0a1、0aa1...
{} {n} 指定匹配n个以上 awk '/ab{2}/p' 匹配包含ab,且a或b连续为2次以上:abb
{n,m} 指定匹配 n-m 个 awk '/ab{2,3}/p' 匹配包含ab,且a或b连续为2-3次:abb、aaab

5. 数学运算

第一列加2
seq 1 10 |awk '{print $1 + 2}'

第一列减2
seq 1 10 |awk '{print $1 - 2}'

第一列乘以2
seq 1 10 |awk '{print $1 * 2}'

第一列除以2 (支持浮点数)
seq 1 10 |awk '{print $1 / 2}'

第一列除以2取余
seq 1 10 |awk '{print $1 % 2}'

第一列2次幂
seq 1 10 |awk '{print $1 ^ 2}'

三目运算
seq 1 3  |awk '{print $0==2 ? "是2" : "不是2"}'

求所有数之和
seq 1 10 |awk '{sum += $1} END{print sum}'    # 结果55

求最大值
seq 1 10 |awk 'BEGIN{max = 0} {if ($1+0 > max+0) max=$1} END{print max}'

求最小值
seq 1 10 |awk 'BEGIN{min = 65536} {if ($1+0 < min+0) min=$1} END{print min}'

求平均值
seq 1 10 |awk '{sum += $1} END{print sum/NR}'

6. IF判断

匹配第1列大于1,且最后一列等于9的行
awk '{if($1 > 0 && $NF == 9) print $0}' file.txt

匹配第1列大于1或最后1列等于8的行
awk '{if($1 > 0 || $NF == 8) print $0}' file.txt

判断第1列等于3
seq 5 |awk '{if ($1 == "3") print $0}'

包含3的行输出yes,否则输出no
seq 5 |awk '{if ($0 == "3") print "yes"; else print "no"}'

多分支
seq 1 10 |awk '{
    if($1==4)
        {print "yes"}
    else
        if($1==6)
            {print "yes"}
    else
        if($1==9)
            {print "yes"}
    else
        {print "no"}}'

7. 循环语句

7.1. while 循环

循环 1-10
awk 'BEGIN{ i=1; while(i <= 10) {print i; i++}}'

循环 1-10,且每个数字后面添加 aaa 字样
awk 'BEGIN{ i=1; while(i <= 10) {print i "aaa"; i++}}'

定义变量 a=abcd,循环10次 abcd
awk -v 'a=abcd' 'BEGIN{ i=1; while(i <= 10) {print a; i++}}'

7.2. for 循环

遍历1-10
awk 'BEGIN{for (i=1; i<=10; i++) print i}'

打印10次abc
awk 'BEGIN{for (i=1; i<=10; i++) print "abc"}'

7.3. 跳出循环

跳出整个循环 break
awk 'BEGIN{ for(i=1; i<=10; i++) {if (i==3) break; print i}}'

跳出当前循环 continue
awk 'BEGIN{ for(i=1; i<=10; i++) {if (i==3) continue; print i}}'

8. awk 内置函数

8.1. 生成随机数

使用awk内置函数:rand() 和 srand()

生成随机数 0-1
awk 'BEGIN{srand(); print rand()}'

生成随机数 1-100(int表示转换为整数)
awk 'BEGIN{srand(); print int(rand() * 100)}'

生成随机数 1w-10w
awk 'BEGIN{srand(); num=int(rand() * 100000); if(num < 10000) (num += 10000); print num}'

8.2. 时间戳转换

输出当前时间戳
awk 'BEGIN{print systime()}'

转换时间戳为日期时间格式
echo "1662973166" |awk '{print strftime("%Y-%m-%d %H:%M:%S",$0)}'

8.3. 文件比较

获取两个文件相同部分
awk 'FNR==NR{a[$0];next}{if($0 in a)print $0}' file1 file2

找出不包含file1内容的file2内容
awk 'FNR==NR{a[$0];next}!($0 in a)' file1 file2

找出不包含file2内容的file1内容
awk 'FNR==NR{a[$0];next}!($0 in a)' file2 file1

9. 文本三剑客其他命令

Linux命令_sed常用指南

Linux命令_grep常用指南

本文含有隐藏内容,请 开通VIP 后查看