Linux grep awk sed 用法简介

grep

grep [options] regex [file...]

regex 是指一个正则表达式

  • -i : 忽略大小写。不会区分大小写字符。也可用–ignore-case 来指定。
  • -v : 不匹配。通常,grep 程序会打印包含匹配项的文本行。这个选项导致 grep 程序只会打印不包含匹配项的文本行。也可用–invert-match 来指定。
  • -c : 打印匹配的数量(或者是不匹配的数目,若指定了-v 选项),而不是文本行本身。 也可用–count 选项来指定。
  • -l : 打印包含匹配项的文件名,而不是文本行本身,也可用–files-with-matches 选项来指定。
  • -L : 相似于-l 选项,但是只是打印不包含匹配项的文件名。也可用–files-without-match 来指定。
  • -n : 在每个匹配行之前打印出其位于文件中的相应行号。也可用–line-number 选项来指定。
  • -h : 应用于多文件搜索,不输出文件名。也可用–no-filename 选项来指定。

正则表达式regex:

  • . 匹配任意字符,例如 .zip 匹配四个字符,任意一个字符和zip,注意 zip 三个字符不能被匹配,因为 . 一个任意字符必须有。即一个任意字符带上zip三个字符,一共四个字符才行
  • [bg]zip,匹配 bzip 或者 gzip;[^bg]zip,匹配不是 bzip 或 gzip,[^bg] 也必须占一个字符,zip 不能被匹配因为前面没有一个非 bg 的字符,所以一共匹配四个字符。一个否定的字符集仍然在给定位置要求一个字符, 但是这个字符必须不是否定字符集的成员

BRE 可辨认的元字符:

^ $ [ ] . *

ERE 添加了以下元字符

( ) { } + ? |

在 BRE 中 字符“(”,“)”,“{”,和 “}”用反斜杠转义后,然而在 ERE 中,在任意元字符之前加上反斜杠会导致其被看作是一个文本字符。

grep 正则表达式默认使用 BRE,要想使用扩展正则表达式,可以用 egrep 命令。也可以给 grep 命令加个 -E 的选项。

为了把 alternation 和其它正则表达式元素结合起来,我们可以使用()来分离 alternation。

# 匹配以 bz 或 gz 或 zip 开头的字符串行
grep -Eh '^(bz|gz|zip)' dirlist*.txt

# 匹配以 以bz开头 或包含 gz 或 包含zip 字符串行
grep -Eh '^bz|gz|zip' dirlist*txt

sort

排序,可按照文本行中的某个列字段排序,sort 命令把空白字符(空格和制表符)当做是列的分割符,也可指定按数值排序,或者指定按某个列字段的一部分进行排序,还可通过 -t 选项指定分隔符。

具体选项:

  • -b :(–ignore-leading-blanks)默认情况下,对整行进行排序,从每行的第一个字符开始。这个选项导致 sort 程序忽略 每行开头的空格,从第一个非空白字符开始排序。
  • -f : (–ignore-case)让排序不区分大小写。
  • -n : (–numeric-sort)基于字符串的数值来排序。使用此选项允许根据数字值执行排序,而不是字母值。
  • -r : (–reverse)按相反顺序排序。结果按照降序排列,而不是升序。
  • -k : (–key=field1[,field2])对从 field1到 field2之间的字符排序,而不是整个文本行。看下面的讨论。
  • -m : (–merge)把每个参数看作是一个预先排好序的文件。把多个文件合并成一个排好序的文件,而没有执行额外的排序。
  • -o : (–output=file)把排好序的输出结果发送到文件,而不是标准输出。
  • -t : (–field-separator=char)定义域分隔字符。默认情况下,域由空格或制表符分隔。
#以 : 为分隔符 按第7个字段排序
sort -t ':' -k 7 /etc/passwd

#按第三个字段的第7个字符到第三个字段结尾的字符的数字进行逆向排序 忽略开头的空格
sort -k3.7nbr ./distros.txt

uniq

与 sort 程序相比,这个 uniq 程序是个轻量级程序。uniq 执行一个看似琐碎的行为。当给定一个 排好序的文件(包括标准输出),uniq 会删除任意重复行,并且把结果发送到标准输出。 它常常和 sort 程序一块使用,来清理重复的输出。

选项如下:

  • -c : 输出所有的重复行,并且每行开头显示重复的次数。
  • -d : 只输出重复行,而不是特有的文本行。
  • -f n : 忽略每行开头的 n 个字段,字段之间由空格分隔,正如 sort 程序中的空格分隔符;然而, 不同于 sort 程序,uniq 没有选项来设置备用的字段分隔符。
  • -i : 在比较文本行的时候忽略大小写。
  • -s n : 跳过(忽略)每行开头的 n 个字符。
  • -u : 只输出独有的文本行。这是默认的。

对于一个文件 foo.txt 里面有如下行:

cat foo.txt
a
b
c
d
a
b
c
d
#执行 uniq foo.txt ,将原样输出
#执行 sort foo.txt | uniq 将排序后去重输出

这是因为 uniq 只会删除相邻的重复行。

cut

这个 cut 程序被用来从文本行中抽取文本,并把其输出到标准输出。它能够接受多个文件参数或者 标准输入。

选项如下:

  • -c : 从文本行中抽取由 char_list 定义的文本。这个列表可能由一个或多个逗号 分隔开的数值区间组成。
  • -f : 从文本行中抽取一个或多个由 field_list 定义的字段。这个列表可能 包括一个或多个字段,或由逗号分隔开的字段区间.
  • -d : 当指定-f 选项之后,使用 delim_char 做为字段分隔符。默认情况下, 字段之间必须由单个 tab 字符分隔开。
  • –complement : 抽取整个文本行,除了那些由-c 和/或-f 选项指定的文本。

正如我们所看到的,cut 程序抽取文本的方式相当不灵活。cut 命令最好用来从其它程序产生的文件中 抽取文本,而不是从人们直接输入的文本中抽取。

从 /etc/passwd 中抽取用户名:
/etc/passwd 中以 : 做为分割

cut -d ":" -f 1 /etc/passwd

sed

sed 命令格式:
sed [选项] 命令 文件(可以一个也可以多个)

sed [options] 'command' file(s)
选项
  • -e

替换操作:s命令

替换文本中的字符串:将 front 替换成 back,结果输出 back

echo 'front' | sed 's/front/back/'

-n选项和p命令一起使用表示只打印那些发生替换的行:

sed -n 's/test/TEST/p' file

直接编辑文件选项-i,会匹配file文件中每一行中的所有book替换为books

sed -i 's/book/books/g' file
sed 替换标记:
  • g 表示行内全面替换。
  • p 表示打印行。
  • w 表示把行写入一个文件。
  • x 表示互换模板块中的文本和缓冲区中的文本。
  • y 表示把一个字符翻译为另外的字符(但是不用于正则表达式)
  • \1 子串匹配标记
  • & 已匹配字符串标记
sed 命令
  • s/regexp/replacement/ 只要找到一个 regexp 匹配项,就替换为 replacement 的内容。 replacement 可能包括特殊字符 &,其等价于由 regexp 匹配的文本。另外, replacement 可能包含序列 \1到 \9,其是 regexp 中相对应的子表达式的内容。更多信息,查看 下面 back references 部分的讨论。在 replacement 末尾的斜杠之后,可以指定一个 可选的标志,来修改 s 命令的行为。
cat distros.txt 
SUSE           10.2     12/07/2006
Fedora         10       11/25/2008
SUSE           11.0     06/19/2008
Ubuntu         8.04     04/24/2008
Fedora         8        11/08/2007

# 打印 [1, 4] 行
执行命令:sed -n '1,4p' distros.txt 
SUSE           10.2     12/07/2006
Fedora         10       11/25/2008
SUSE           11.0     06/19/2008
Ubuntu         8.04     04/24/2008

# 打印被 SUSE 匹配到的行
执行命令:sed -n '/SUSE/p' distros.txt
SUSE           10.2     12/07/2006
SUSE           11.0     06/19/2008

# 打印未被 SUSE 匹配到的行。
执行命令:sed -n '/SUSE/!p' distros.txt
Fedora         10       11/25/2008
Ubuntu         8.04     04/24/2008

sed ‘s/regex/replacement/’ file

#search
11/25/2008

#regex
([0-9]{2})/([0-9]{2})/([0-9]{4})$

#replacement
\3-\1-\2

# sed 命令的 regex 使用 BRE 所以要想用 ERE 里面的元字符(( ) { })需要使用 \ 转义
sed 's/\([0-9]\{2\}\)\/\([0-9]\{2\}\)\/\([0-9]\{4\}\)/\3-\1-\2/' distros.txt

这个功能叫做 逆参照 ,像这样工作:如果序列 \n 出现在 replacement 中 ,这里 n 是指从 1 到 9 的数字,则这个序列指的是在前面正则表达式中相对应的子表达式。为了 创建这个子表达式,我们简单地把它们用圆括号括起来,

Linux 去除回车(将回车替换成空格):

sed ':a;N;$!ba;s/\n/ /g'
sed 应用举例

关键 options 介绍:

  • n: 安静模式。一般sed用法中,所有来自STDIN的数据都会被输出到屏幕上,使用-n只有被sed处理的行才会列出来。如果不使用-n,使用sed打印时,会把输入流和处理的信息都打印一遍
  • a:append,追加文本
  • i:insert,插入文本
  • d:delete,删除文本
  • s:模式匹配替换
  • p:打印文本
  1. 在指定行插入或追加: a, i
    • 在test.txt第一行前插入:sed "1 i This is a test file" test.txt
    • 在test.txt最后一行追加:sed "$ a This is the end of file" test.txt
  2. 删除:d
    • 删除test.txt第二行:sed "2d" test.txt
    • 删除test.txt符合正则表达式/fish的行:sed "/fish/d" test.txt
  3. 修改文本:s
    • 将text.txt中love替换为like:sed "s/love/like/g" test.txt (/g表示全局匹配)
  4. 打印文本:p
    • 输出test.txt的第5-7行:sed -n "5,7p" test.txt (-n的作用就显示出来了,可以去除-n查看效果)

printf

格式字符串可能包含文字文本(如“我格式化了这个字符串:” “I formatted the string:”),转义序列(例如\n,换行符)和以%字符开头的序列,这被称为转换规范。

命令格式:

printf  format-string  [arguments...]

# 注意在 awk 中的使用
awk '{printf "%s\t%s", $1, $2}' # arguements 用逗号隔开

常用的数据类型:

  • d 将数字格式化为带符号的十进制整数
  • f 格式化并输出浮点数
  • o 将整数格式化为八进制数
  • s 将字符串格式化
  • x 将整数格式化为十六进制数,必要时使用小写a-f
  • X 与 x 相同,但变为大写
  • % 打印 % 符号 (比如,指定 “%%”)

awk

awk '条件 {操作}' 文件
awk '$9 == 500 {print $9, $7}' access.log

awk 的内建变量:

  • $0 当前记录(这个变量中存放着整个行的内容)
  • $1~n 当前记录的第n个字段,字段间由FS分隔
  • FS 输入字段分隔符 默认是空格或Tab
  • NF 当前记录中的字段个数,就是有多少列
  • NR 已经读出的记录数,就是行号,从1开始,如果有多个文件话,这个值也是不断累加中。
  • FNR 当前记录数,与NR不同的是,这个值会是各个文件自己的行号
  • RS 输入的记录分隔符, 默认为换行符
  • OFS 输出字段分隔符, 默认也是空格
  • ORS 输出的记录分隔符,默认为换行符
  • FILENAME 当前输入文件的名字

指定 :为分隔符

# 以下两句效果一样
awk 'BEGIN{FS=":"} {print $1, $3, $6}' /etc/passwd
awk -F ":" '{print $1, $3, $6}' /etc/passwd

# 如果要指定多种分割符,例如指定 : ; 作为分割符
awk -F '[:;]'

# 以 \t 作为输出分割符
awk -F ':' '{print $1, $3, $6}' OFS='\t' /etc/passwd

比较运算符:
==, !=, >, <, >=, <=, ~

下面看字符串匹配的例子:

# 第一行或者第 6 列匹配到 FIN 的
awk '$6 ~ /FIN/ || NR ==1 {print $1, $3, $6}' OFS='\t' netstat.txt

# awk 也可以像 grep 一样去匹配
awk '/LISTEN/' netstat.txt

# 可以用 FIN|TIME 来匹配 FIN 或者 TIME :
awk '$6 ~ /FIN|TIME/ || NR == 1 {print NR, $4, $5, $6}' OFS="\t" netstat.txt

再复杂一点,带上 if else 语句

awk 'NR!=1{if($6 ~ /TIME|ESTABLISHED/) print > "1.txt"; else if($6 ~ /LISTEN/) print > "2.txt"; else print > "3.txt"}' netstat.txt

awk 的 BEGIN 和END关键字

  • BEGIN {这里面放的是执行前的语句}
  • {这里面放的是处理每一行时要执行的语句}
  • END {这里面放的是处理完所有的执行后要执行的语句}

awk 常用内建变量

  • $n 当前记录的第n个字段,字段间由FS分隔
  • $0 完整的输入记录
  • FILENAME 当前文件名
  • NF 一条记录的字段的数目
  • NR 已经读出的记录数,就是行号,从1开始
  • OFS 输出记录分隔符(输出换行符),输出时用指定的符号代替换行符
  • ORS 输出记录分隔符(默认值是一个换行符)
  • 记录分隔符(默认是一个换行符)
  • FS 字段分隔符(默认是任何空格)

**注意:**一行称为一条记录,一列称为一个字段

例子

1、行列转换问题
cat file.txt
1 2 3 4 5
1 2 3 4 5
1 2 3 4 5
awk '{for(i=1;i<=NF;i++)arr[NR,i]=$i}END{for(col=1;col<=NF;col++)for(row=1;row<=NR;row++)printf row==NR?arr[row,col] RS:arr[row,col] FS}' file.txt
1 1 1
2 2 2
3 3 3
4 4 4
5 5 5

解析:NF 为每一行的字段数,相当于有多少列cols,NR 为读到的行数,读取结束后,NR 就等于总行数rows。因为 awk 读取的时候是一行一行读的,读一行就会执行一下后面的操作,所以每读一行就会执行一次 for 循环,NF 为读到的该行的列数,NR 为当前所读的行号,读一行就遍历该行,将其每列放入数组。END 后面的操作是在读取结束之后进行的,遍历打印二维数组


LeetCode 194. Medium 用到该方法

2、Nginx access.log 日志相关操作

问题描述:

1、取出 access.log 中状态码为 500 的 url 要求去重后取出前 100 条(access.log 中字段以空格分割,第9列为状态吗,第 7 列为url)

awk '($9=="500") {print $7}' | sort -u | head -n 1000

2、统计接口的访问次数,根据 access.log 日志 统计各个 URL 的访问次数,去除静态资源(css、js、html、png、jpg、jpeg、gif),以及接口后的 parameter(?问号后面的内容),并按照访问次数逆序排序

awk '$7 !~ /\.(css|js|html|png|jpg|jpeg|gif)/ {print $7}' access.log| sed 's/\?.*//' | sort |uniq -c | sort -k1,1nr

3、打印 file.txt 中第 10 行的内容
LeetCode 195. Tenth Line (Medium)

  1. 解法一 awk: awk "NR==10" file.txt
  2. 解法二 sed: sed -n "10p" file.txt
  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值