2025年3月17日 星期一 甲辰(龙)年 月十六 设为首页 加入收藏
rss
您当前的位置:首页 > 计算机 > 系统应用 > Linux

Linux文本命令技巧(上)

时间:01-25来源:作者:点击数:58

简介#

前一篇我介绍了awk,这是一个全能的文本处理神器,因为它本身就是一门编程语言了,但对于很多场景,使用Linux预设的一些文本处理命令,会更方便快捷,如grep、sed等。

本篇就来介绍一下Linux上常用的文本处理命令,由于内容较多,分为上下两篇,这里是上篇。

查看文本内容#

主要包含cat、less、grep、head、tail,请看示例:

  • # 用seq构造数据,tee的作用是写入文件的同时也将内容打印到屏幕上
  • $ seq 5|tee data.txt
  • 1
  • 2
  • 3
  • 4
  • 5

cat

  • # cat可直接查看文件内容,加上-A选项可查看文件中不可见的特殊字符
  • $ cat data.txt
  • 1
  • 2
  • 3
  • 4
  • 5

less

  • # less查看文件,其中-N表示显示行号,-S表示不换行显示
  • # ctrl+f向前翻页,ctrl+b向后翻页,输入/再输入xxx搜索xxx,接着按n搜索下一个,N搜索上一下
  • $ less -N -S data.txt
  • # less常用来查看一页显示不了的情况,比如tree直接查看当前目录结构,可能会让你的屏幕刷一大堆文字(非常实用)
  • $ tree | less -S

grep

  • # grep可以使用正则表达式过滤文件内容,一般建议你加上-E,如果你想使用正则中的\d,建议你将-E换成-P
  • $ grep -E '[345]' data.txt
  • 3
  • 4
  • 5
  • # 在当前目录递归的查找包含ERROR文件的行(非常实用)
  • $ grep -rn 'ERROR' .
  • # 输出查找到的行,以及其后面的2行,常用于查找异常栈(非常实用)
  • $ cat data.txt|grep -A 2 '[2]'
  • 2
  • 3
  • 4
  • # 查找日志文件中最后产生的10条错误日志,-i用于忽略大小写,tac用于倒序输出行(非常实用)
  • tac app.log|grep -i -m10 'ERROR'|tac

head与tail

  • # 获取前两行
  • $ cat data.txt|head -n2
  • 1
  • 2
  • # 获取后两行
  • $ cat data.txt|tail -n2
  • 4
  • 5
  • # 获取第3行到第4行
  • $ cat data.txt|tail -n +3|head -n2
  • 3
  • 4
  • # -f会在文件写新行时,同步将其显示出来,常用于动态观察日志(非常实用)
  • # 在less中,也可以按Shift + f实现类似效果
  • $ tail -f app.log

修改文本内容#

tr

tr用于替换删除单个字符,如下:

  • # 替换a为c
  • $ echo aba|tr a c
  • cbc
  • # 替换为大写
  • $ echo aba|tr [a-z] [A-Z]
  • ABA
  • # 删除换行
  • $ seq 5|tr -d $'\n'
  • 12345

cut

用于字符串分割,如下:

  • $ echo 'a,b,c,d,e'|cut -d, -f2
  • b
  • $ echo 'a,b,c,d,e'|cut -d, -f2-4
  • b,c,d
  • $ echo 'a,b,c,d,e'|cut -d, -f2-
  • b,c,d,e
  • $ echo 'a,b,c,d,e'|cut -d, -f-2
  • a,b

sed

用于替换修改文本,有流文本编辑器之称。

基本语法形如pattern action,sed会读取每一行,看是否匹配pattern,如果匹配则执行action。

sed '3,5 s/a/c/g'将第3到5行中的a替换为c,其中3,5为pattern部分,s/a/c/g为action部分,只有满足pattern条件的行,action才会执行,pattern部分可以省略,这样每一行都会执行action。

  • # yes可以用来不断的重复生成字符串,以此作为我们的测试数据
  • $ yes abcde|head -n5
  • abcde
  • abcde
  • abcde
  • abcde
  • abcde
  • # 第3到5行中的a替换为c,其中的g表示所有的a,都替换为c
  • $ yes abcde|head -n5|sed '3,5 s/a/c/g'
  • abcde
  • abcde
  • cbcde
  • cbcde
  • cbcde

另外pattern action还可以是如下的形式:

  1. 可以组合写多个,如sed '3,5 s/a/c/g; 2,4 s/b/d/g'表示第3行到第5行的a替换为c,第2行到第4行的b替换为d。
  2. 还可以嵌套,如sed '3,5{3,4 s/a/c/g; 4,5 s/b/d/g}'表示第3到5行中,其中3到4行执行a替换为c,第4到5行执行b替换为d。其实你可以认为在action只有一个时,大括号被省略了。
  3. 还可以求反,如sed '3,5! s/a/c/g'表示非第3到5行的行,将a替换为c。
  • # 第3行到第5的a替换为c,第2行到第4行的b替换为d
  • $ yes abcde|head -n5|sed '3,5 s/a/c/g; 2,4 s/b/d/g'
  • abcde
  • adcde
  • cdcde
  • cdcde
  • cbcde
  • # 第3到5行中,其中3到4行执行a替换为c,第4到5行执行b替换为d
  • $ yes abcde|head -n5|sed '3,5{3,4 s/a/c/g; 4,5 s/b/d/g}'
  • abcde
  • abcde
  • cbcde
  • cdcde
  • adcde
  • # 非第3到5行的行,将a替换为c
  • $ yes abcde|head -n5|sed '3,5! s/a/c/g'
  • cbcde
  • cbcde
  • abcde
  • abcde
  • abcde

另外sed默认会打印执行action处理后的每一行,加上-n选项可以关掉默认打印,如下:

  • # 显示1到3行,这里action为p,表示打印,-n用来关闭默认打印,不然1到3行会打印2遍,p一般都和-n配合使用
  • $ seq 5|sed -n '1,3 p'
  • 1
  • 2
  • 3
  • # pattern部分可以使用正则表达式,注意sed中的正则也不能使用\d,且记得时常搭配-E选项
  • # 注意pattern部分和action部分是可以随意组合的,也就是说正则形式的pattern也可以和s搭配使用
  • $ seq 5|sed -n '/[2-4]/ p'
  • 2
  • 3
  • 4
  • # pattern部分也可以是逗号分隔的两个正则表达式,匹配从找到第一个正则表达式开始的行,到找到第二个正则表达式的行结束
  • $ seq 5|sed -n '/[2]/,/[4]/ p'
  • 2
  • 3
  • 4
  • # 打印第1行,以及之后第间隔2行的行
  • $ seq 5|sed -n '1~2 p'
  • 1
  • 3
  • 5

除了s(替换)与p(打印)外,还有d(删除)、i(插入)、a(追加)、c(修改),如下:

  • # 删除包含1和2的行
  • $ seq 3|sed '/[1-2]/ d'
  • 3
  • # 向前插入一行,常用于设置csv标题
  • $ seq 3|sed '1 i\id'
  • id
  • 1
  • 2
  • 3
  • # 在最后一行之后追加一行
  • $ seq 3|sed '$ a\id'
  • 1
  • 2
  • 3
  • id
  • # 将第一行整行直接修改为id
  • $ seq 3|sed '1 c\id'
  • id
  • 2
  • 3

另外,s(替换)还有一些细节,这些细节实际上非常有用,体会一下:

  • # 替换可以使用正则的捕获组功能
  • $ echo 'id=1,name=zs'|sed -E 's/id=(\w+),name=(\w+)/\1 \2/'
  • 1 zs
  • # g表示将所有的a替换为c
  • $ echo 'a,a,a,a'|sed 's/a/c/g'
  • c,c,c,c
  • # 3g表示将第3次匹配到的a以及后面匹配到的a,都替换为c
  • $ echo 'a,a,a,a'|sed 's/a/c/3g'
  • a,a,c,c
  • # 没有g只能替换第1次匹配
  • $ echo 'a,a,a,a'|sed 's/a/c/'
  • c,a,a,a
  • # 3表示只替换第3次匹配到的a为c
  • $ echo 'a,a,a,a'|sed 's/a/c/3'
  • a,a,c,a

排序与分析#

Linux中sort、wc、uniq、comm可用于做一些简单的排序与分析任务,如下为示例文本数据:

  • #用shell的here document语法,将data.txt中生成如下内容
  • $ cat > data.txt <<eof
  • > 2,zhangsan
  • > 11,lisi
  • > 3,wangwu
  • > eof
  • $ cat data.txt
  • 2,zhangsan
  • 11,lisi
  • 3,wangwu

sort

  • # -t用于指定字段分隔符,-k1表示使用第一个字段排序,sort默认使用空白字符作为字符分隔符,且默认升序排序
  • $ cat data.txt |sort -t, -k1
  • 11,lisi
  • 2,zhangsan
  • 3,wangwu
  • # -n表示将字段值作为数字进行比较,不然就当成字符串比较,所以之前11排在2的前面
  • $ cat data.txt |sort -t, -k1 -n
  • 2,zhangsan
  • 3,wangwu
  • 11,lisi
  • # -r表示倒序排序
  • $ cat data.txt |sort -t, -k1 -n -r
  • 11,lisi
  • 3,wangwu
  • 2,zhangsan

wc

  • # 统计行数(常用)
  • $ cat data.txt |wc -l
  • 3
  • # 统计行数其实sed也可以,=号表示输出当前行号
  • $ cat data.txt |sed -n '$ ='
  • 3
  • # wc -c可用于获取中英混写情况下,在各字符编码下的占用字节数
  • $ echo -n 'code日记'|iconv -t gbk|wc -c
  • 8
  • $ echo -n 'code日记'|iconv -t utf8|wc -c
  • 10

uniq

uniq可以实现简单的分组计数,uniq处理的数据必须是已排好序的,所以一般使用uniq之前需要先sort一下,此命令非常实用。

  • # 查看各状态socket的数量
  • $ ss -nat|awk 'NR>1{print $1}'|sort|uniq -c
  • 1 ESTAB

comm

comm用于对比两个文件中的行,求它们的差集与交集,输入的文件也需要先sort,此命令非常实用。

  • # 第一列是comm第1部分相对第2部分的差集,第二列是comm第2部分相对第1部分的差集,第三列是交集
  • $ comm <(seq 0 5) <(seq 1 6)
  • 0
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • # -1 -2表示不显示第一列与第二列,所以只显示了交集这一列
  • $ comm -1 -2 <(seq 0 5) <(seq 1 6)
  • 1
  • 2
  • 3
  • 4
  • 5
  • # 当然-2 -3就可显示第一列的差集了
  • $ comm -23 <(seq 0 5) <(seq 1 6)
  • 0

多文件内容处理#

这里需要两个示例文件,如下:

  • $ cat person.txt
  • 1,zhangsan
  • 2,lisi
  • 3,wangwu
  • $ cat score.txt
  • 1,92
  • 2,78
  • 3,93

paste

paste命令初一看以为是用来粘贴的,实际上并不是,它更像是做多文件的列式合并,如下:

  • # 这看起来就像是两文件中相应行,合并到1行,用tab符分隔
  • $ paste person.txt score.txt
  • 1,zhangsan 1,92
  • 2,lisi 2,78
  • 3,wangwu 3,93
  • # 这种列没对齐的数据,可以使用column -t使其对齐
  • $ paste person.txt score.txt|column -t
  • 1,zhangsan 1,92
  • 2,lisi 2,78
  • 3,wangwu 3,93
  • # 指定:为合并分隔符
  • $ paste person.txt score.txt -d ':'
  • 1,zhangsan:1,92
  • 2,lisi:2,78
  • 3,wangwu:3,93
  • # 体会一下-s选项(非常实用的选项)
  • $ seq 5|paste -s -d,
  • 1,2,3,4,5
  • $ paste -sd, <(seq 1 5) <(seq 2 6)
  • 1,2,3,4,5
  • 2,3,4,5,6
  • # 分组展示,-表示标准输入,非常实用
  • $ seq 5|paste -d, - - -
  • 1,2,3
  • 4,5,

join

join命令可以实现类似SQL中join的效果,join命令使用的文件,也应该是事先排好序的,如下:

  • # -1 1表示第一个文件使用第一个字段作为联接字段
  • # -2 1表示第2个文件使用第一个字段作为联接字段
  • # -t, 表示使用,作为字段分隔符
  • $ join -1 1 -2 1 -t, -a1 person.txt score.txt
  • 1,zhangsan,92
  • 2,lisi,78
  • 3,wangwu,93

总结#

Linux中的每个文本命令很多,每个看起来都不起眼,但它们组合起来可以做到很多事情。

且Linux中的grep、sed命令,当发现写的正则明明正确,执行却报错时,请加上-E选项,且不要使用\d,详细可搜索BRE、ERE、PCRE的区别。

方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门