grep [options] regex [file...]
regex 是指一个正则表达式
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 命令把空白字符(空格和制表符)当做是列的分割符,也可指定按数值排序,或者指定按某个列字段的一部分进行排序,还可通过 -t 选项指定分隔符。
具体选项:
#以 : 为分隔符 按第7个字段排序
sort -t ':' -k 7 /etc/passwd
#按第三个字段的第7个字符到第三个字段结尾的字符的数字进行逆向排序 忽略开头的空格
sort -k3.7nbr ./distros.txt
与 sort 程序相比,这个 uniq 程序是个轻量级程序。uniq 执行一个看似琐碎的行为。当给定一个 排好序的文件(包括标准输出),uniq 会删除任意重复行,并且把结果发送到标准输出。 它常常和 sort 程序一块使用,来清理重复的输出。
选项如下:
对于一个文件 foo.txt 里面有如下行:
cat foo.txt
a
b
c
d
a
b
c
d
#执行 uniq foo.txt ,将原样输出
#执行 sort foo.txt | uniq 将排序后去重输出
这是因为 uniq 只会删除相邻的重复行。
这个 cut 程序被用来从文本行中抽取文本,并把其输出到标准输出。它能够接受多个文件参数或者 标准输入。
选项如下:
正如我们所看到的,cut 程序抽取文本的方式相当不灵活。cut 命令最好用来从其它程序产生的文件中 抽取文本,而不是从人们直接输入的文本中抽取。
从 /etc/passwd 中抽取用户名:
/etc/passwd 中以 : 做为分割
cut -d ":" -f 1 /etc/passwd
sed 命令格式:
sed [选项] 命令 文件(可以一个也可以多个)
sed [options] 'command' file(s)
替换操作: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
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'
关键 options 介绍:
n
: 安静模式。一般sed用法中,所有来自STDIN的数据都会被输出到屏幕上,使用-n只有被sed处理的行才会列出来。如果不使用-n,使用sed打印时,会把输入流和处理的信息都打印一遍a
:append,追加文本i
:insert,插入文本d
:delete,删除文本s
:模式匹配替换p
:打印文本a, i
sed "1 i This is a test file" test.txt
sed "$ a This is the end of file" test.txt
d
sed "2d" test.txt
sed "/fish/d" test.txt
s
sed "s/love/like/g" test.txt
(/g表示全局匹配)p
sed -n "5,7p" test.txt
(-n的作用就显示出来了,可以去除-n查看效果)格式字符串可能包含文字文本(如“我格式化了这个字符串:” “I formatted the string:”),转义序列(例如\n,换行符)和以%字符开头的序列,这被称为转换规范。
命令格式:
printf format-string [arguments...]
# 注意在 awk 中的使用
awk '{printf "%s\t%s", $1, $2}' # arguements 用逗号隔开
常用的数据类型:
awk '条件 {操作}' 文件
awk '$9 == 500 {print $9, $7}' access.log
awk 的内建变量:
指定 :为分隔符
# 以下两句效果一样
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
**注意:**一行称为一条记录,一列称为一个字段
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 用到该方法
问题描述:
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)
awk "NR==10" file.txt
sed -n "10p" file.txt