linux grep、sed、awk 咋用

基础

declare

declare 为 shell 解释器自建命令,默认所有变量类型均为字符串,脚本语言(解释器语言)是解释执行的,解释权归自己所有,只要语句自己认识即可,想咋定就咋定

declare(选项)(参数)

选项
 -: 给变量设置类型属性  
  +: 取消变量的类型属性  
  -a:将变量声明为数组型  
  -i:将变量声明为整型  
  -x:将变量声明为环境变量  
  -r:将变量声明为只读变量 
  -p:查看变量的被声明的类型
参数

# 声明 x,y,z,默认字符串连接

[cmd] x=1
[cmd] declare -p x
      declare -- x="1"
[cmd] y=1
[cmd] z=$x+$y && echo $z
      1+1
[cmd] declare -i z
[cmd] declare -p z
      declare -i z="1+1"
      
# 声明 i_z 整形,加法不再默认字符串连接
[cmd] declare -i i_z=$x+$y && echo $i_z
      2
[cmd] declare -p i_z
      declare -i i_z="2"

# 数组,不需要声明
[cmd] a_x1=1
[cmd] a_x2=2
[cmd] declare -p a_x
      declare -a a_x='([0]="1" [1]="2")'
      
# 声明只读,可以只有声明,不赋值,不可修改,不可 -p
[cmd] declare -r r_x
[cmd] declare -p r_x
      -bash: declare: r_x: not found
[cmd] declare -r x
[cmd] declare -p x
      declare -r x="1"
[cmd] declare -r i_z

# i_z 整形只读,只读设置不可撤销
[cmd] declare -p i_z
      declare -ir i_z="2"
[cmd] i_z=4
      -bash: i_z: readonly variable
[cmd] declare +r i_z
      -bash: declare: i_z: readonly variable

 引号

特殊字符,有些字符在 shell 中具有特殊含义,需要转义处理,如下表

关键字,充当指令的字符,有些关键字使用特殊字符

单引号、双引号、无引号,在 shell 中,默认所有输入都为字符串,不需要任何引号,规定双引号无引号等同,加双引号是为了减少失误。shell 中这些特殊输入输出需要加反斜杠 \( 例如 \# 表示 #,\! 表示 !  )。若不加反斜杠,使用单引号也可达到同样效果

#,  ;,  ;;,  . .,  .,  "",  '',  \,  /,  `,  :,  !,  *,  ?,  $,  (),  {},  [],  [[]],  (()),  >& >>& >> <,  << <<<,  \<, \>,  |,  >|,  ||,  &,  &&,  ~,  !,  ,,  ^

POSIX 正则表达式规范

包括 BRE(基本型)和 ERE(扩展型)两类规则,互不兼容。BRE 规定关键字字符:., \, [, ^, $, * ERE中规定关键字字符 7 个,(, ), {, }, +, ?, | grep、vi、sed 工具遵循 BRE 规范,grep -e, egrep, awk 工具遵循 ERE 规范。对于这些工具,会按照相应规范处理这些关键字符。其它没有被当作关键字的特殊字符,加反斜杠输入输出。

实例分析,查找字符串 xoo, grep ".o\{2\}" filename。这里 . 本来是特殊字符,这里 grep 选作关键字,\{  和 \} 表示花括号, grep 将参数识别为 .o{2},如下是查找特殊字符的命令

[cmd]grep '\"'  one.txt -on
[cmd]grep "\\\\\\\\"  one.txt
[cmd]grep "'"  one.txt -on
[cmd]grep "\\$"  one.txt -on
[cmd]grep "|"  one.txt -on
[cmd]grep "\\^"  one.txt -on
[cmd]grep "\^" one.txt -on
[cmd]grep "#" one.txt -on
[cmd]grep ";" one.txt -on
[cmd]grep "." one.txt -on
[cmd]grep "\." one.txt -on
[cmd]grep "/" one.txt 
[cmd]grep "\*" one.txt 
[cmd]grep "\?" one.txt 
[cmd]grep "\[" one.txt -on
[cmd]grep "\]" one.txt -on
[cmd]grep "<" one.txt -on
[cmd]grep ">" one.txt -on
[cmd]grep "||" one.txt -on
[cmd]grep "&" one.txt -on
[cmd]grep "&&" one.txt -on
[cmd]grep "~" one.txt -on
[cmd]grep "\!" one.txt -on

 grep 命令

以行为单位查找匹配内容,包含查找内容的行

grep [OPTIONS] [-e PATTERN | -f FILE] [FILE...]
查找 .gz 压缩文件用 zgrep 命令,跟 grep 基本相同
OPTIONS:
-v:反选
-w: 单词匹配
-x: 整行匹配
-n:打印行号
-o:grep 默认会输出匹配的行,如果只想输出匹配的字符串,加该参数
-F: 不要使用正则匹配,直接匹配

-e PATTERN:可以有多个,例如 -e  "ab" -e "cd",查找 ab 或者 cd,PATTERN 按照相关正则标准写
-f FILE:指定关键字文件,查找少量关键字用 -e PATTERN ,查找几百个呢,用文件比较好
最后是一个被查找的文件列表

 sed

一般用于对文件进行格式化,默认不会修改源文件,通过读取文件流到缓冲区,对缓冲行执行相关操作以标准输出流的方式输出,在输出时,会输出源行和修改后行内容。加 -i 参数会直接修改源文件,加 -n 只输出操作后行内容,没操作不输出。

sed [-inV] '/行选择器/动作'
指令:
-i 直接修改源文件
-V 版本信息
动作: a:追加,在当前行后添加一行或多行。当添加多行时,除最后一行外,每行末尾需要用“\”代表数据未完结; c:行替换,用c后面的字符串替换原数据行。当替换多行时,除最后一行外,每行末尾需用“\”代表数据未完结; i:插入,在当前行前插入一行或多行。当插入多行时,除最后一行外,每行末尾需要用“\”代表数据未完结; d:删除,删除指定的行; P:打印,输出指定的行; s:字符串替换,用一个字符串替换另一个字符串。格式为“行范围s/旧字串/新字串/g”(和Vim中的替换格式类似); # 文件内容 [cmd]cat two.txt 11111111a 22222222b 33333333c # 查找含字符串 222 行,并在其之前插入 hello word [cmd]sed '/222/i hello word' two.txt 11111111a hello word 22222222b 33333333c # 查找含字符串 222 行,并在其之后插入 hello word [cmd]sed '/222/a hello word' two.txt 11111111a 22222222b hello word 33333333c # 查找含字符串 222 行,并将改为 hello word 两行 [cmd]sed '/222/c hello \n word' two.txt 11111111a hello word 33333333c # 查找含字符串 222 行,并将该行 b 字符替换为 $ [cmd]sed '/222/s/b/$/g' two.txt 11111111a 22222222$ 33333333c

 awk

一般用于编辑文件。awk '[BEGIN{ commands }]  [pattern{ commands }]  [END{ commands }]'  filename 一个awk脚本通常由BEGIN, 通用语句块,END语句块组成,三部分都是可选的。 脚本通常是被单引号或双引号包住。awk 脚本类似与 js 脚本,功能强大

awk执行过程分析
第一步: 执行BEGIN { commands } 语句块中的语句

BEGIN语句块:在awk开始从输入输出流中读取行之前执行,在BEGIN语句块中执行如变量初始化,打印输出表头等操作。

第二步:从文件或标准输入中读取一行,然后执行 pattern{ commands }语句块。它逐行扫描文件,从第一行到最后一行重复这个过程,直到全部文件都被读取完毕。

pattern语句块:pattern语句块中的通用命令是最重要的部分,它也是可选的。如果没有提供pattern语句块,则默认执行{ print },即打印每一个读取到的行。{ }类似一个循环体,会对文件中的每一行进行迭代,通常将变量初始化语句放在BEGIN语句块中,将打印结果等语句放在END语句块中。

第三步:当读至输入流末尾时,执行END { command }语句块
在awk从输入流中读取完所有的行之后即被执行,比如打印所有行的分析结果这类信息汇总都是在END语句块中完成,它也是一个可选语句块。

内置变量

$0 整行
$1, $2 第一列,第二列
NF 最后一列变量
FS 分隔符字符
NR 当前行号

-F: 指定分隔符
-v: 指定或者修改内部变量
-v OFS="===": 输出分隔符

cat score.txt
Marry   2143 78 84 77
Jack    2321 66 78 45
Tom     2122 48 77 71
Mike    2537 87 97 95
Bob     2415 40 57 62

$ cat cal.awk
#!/bin/awk -f
#运行前
BEGIN {
    math = 0
    english = 0
    computer = 0
 
    printf "NAME    NO.   MATH  ENGLISH  COMPUTER   TOTAL\n"
    printf "---------------------------------------------\n"
}
#运行中
{
    math+=$3
    english+=$4
    computer+=$5
    printf "%-6s %-6s %4d %8d %8d %8d\n", $1, $2, $3,$4,$5, $3+$4+$5
}
#运行后
END {
    printf "---------------------------------------------\n"
    printf "  TOTAL:%10d %8d %8d \n", math, english, computer
    printf "AVERAGE:%10.2f %8.2f %8.2f\n", math/NR, english/NR, computer/NR
}

$ awk -f cal.awk score.txt
NAME    NO.   MATH  ENGLISH  COMPUTER   TOTAL
---------------------------------------------
Marry  2143     78       84       77      239
Jack   2321     66       78       45      189
Tom    2122     48       77       71      196
Mike   2537     87       97       95      279
Bob    2415     40       57       62      159
---------------------------------------------
  TOTAL:       319      393      350
AVERAGE:     63.80    78.60    70.00

分组计数,多个分隔符

111111*****2222222|||||||3333333########444444444&&&&&&&&&55555555
awk -F '[*|#&]+' '{print $3}' 333
awk '{arr[$1]++} END{for(i in arr){print(i ": " arr[i])}}' two.txt

数据统计

样本抽取

shuf -n 1000 srcName > dstName 从 srcName 抽取 1000 行到 dstName。先对样本进行分析,编写相应处理程序,跑样本,得到预测结果后,再处理源数据

文件切割,防止源数据过大,内存溢出

split -l 1000 test.txt -d -a 3 test_
-l:按行分隔,每1000行切割test.txt文件
-d:添加数字后缀
-a:以3位数数字做尾数
test_:分割后的文件的前缀

去重

uniq -c 相同行数量,只能统计相邻行

排序

sort -n -r -t ':' -k 3

-n,用数值排序,而非字典序
-r,倒序
-t ':', 冒号作为分隔符
-k 3,分割后第 3 列

计数

wc -l

posted on 2022-09-30 23:29  一直小飞猫  阅读(138)  评论(0编辑  收藏  举报

导航