20210211-1 Linux基础与应用(中)

 

一、文本操作命令

 

文本操作命令

? cat

? more

? less

? head

? head -2 /etc/profile

? tail

? tail -2 /etc/profile

? tail -f  实时监控日志,日志不断增长时,可以看到最新的当前的日志

如果只想看第 4 行日志,应该怎么办?可以借助管道的概念

[root@localhost ~]# head -4 install.log.syslog2 | tail -1

4d

类似于取交集??

 

? 管道

? cat b.txt | head -3

打开文本b 输入到管道 管道后的进程读取文本前三行;管道前后相当于开两个子进程

[root@localhost ~]# echo $$

4743

$$ 代表当前进程的PID

 

[root@minicent6~]# echo $$

1169 现在是在父进程中

[root@minicent6~]# /bin/bash 打开一个bash,开了一个子进程

[root@minicent6~]# echo$$ 所以进程号变了

1375

[root@minicent6~]# /bin/bash 又打开一个bash,用pstree查看进程结构

20210211-1 Linux基础与应用(中)

[root@minicent6~]# exit 退出到父进程

exit

[root@minicent6~]# echo $$ 退回到 1375

1375

[root@minicent6~]# exit 退出后,pstree查看进程,只有一个了

exit

20210211-1 Linux基础与应用(中)

[root@minicent6~]# echo $$ 打印PID和最初的是一样的,退回到最上面的进程

 

1169

 

所以管道符会自动打开两个进程,而且都是当前进程的子进程,通过bash打开交互

把 cat b.txt的输出作为 head -3 子进程的输入,同时 cat b.txt进程关闭,head -3进程执行完成后也会关闭子进程,输出结果后,回到当前的父进程

 

? | tail -1

? xargs

 

? shell读取用户输入的字符串

? 发现 |,代表有管道

? | 左右被理解为简单命令

? 加工:前一个(左边)简单命令的标准输出

? 指向后一个(右边)简单命令的标准输入

? 注意:后一个简单命令一定能够接受标准输入

 

一个命令的出现一定是为了解决某个问题

如果在root路径下,但是想看etc目录下的内容 可以

[root@localhost ~]# ls -l /etc

 

? xargs:

? 命令

? 1,在标准输入中读取到的内容!

? 2,自己的参数理解为一个字符串

? 模仿shell,做blank切分,第一个子字符串为命令

? 3,将步骤1的内容做为步骤2的命令的选项参数拼接起来

? 4,执行得到的结果

? echo "/" | xargs ls -l

现在在脚本里,想把目录作为变量输入管道后的命令

[root@localhost ~]# echo "/" | ls -l

总用量 12

-rw-------. 1 root root 1523 1月  25 15:15 anaconda-ks.cfg

……

这种方式失败了,并没有接成输入,显示的还是当前目录root下的内容,这时可以用xargs

[root@localhost ~]# echo "/" | xargs ls -l

总用量 28

lrwxrwxrwx.   1 root root    7 1月  25 15:06 bin -> usr/bin

dr-xr-xr-x.   5 root root 4096 1月  25 15:21 boot

drwxr-xr-x.  20 root root 3300 2月   8 21:45 dev

……

现在显示的就是根目录下的内容,xargs把前面的命令作为一个参数传到后面

 

? 打开文件

? vim /path/to/somefile

? vim +# :打开文件,并定位于第#行

? vim +:打开文件,定位至最后一行

? vim +/PATTERN : 打开文件,定位至第一次被PATTERN匹配到的行的行首

vi 是 vim的简化版本,一般vim是需要自己去安装的

[root@localhost ~]# yum -i install vim

如果打开的文本很长,现在需要定位到某一行,不想上下滚动

[root@localhost em]# vi +5 profile

光标就会在第5行的位置,shift+冒号进入末行模式,在末行模式输入:set nu,可以打印行数;输入:set nonu,取消打印行数

如果想直接进入最后一行

[root@localhost em]# vi + profile

如果已经 vi profile 进入命令模式了,想要定位在最后一行,可以按 shift+g,进入末行

 

如果配置文件中的某个字符有误,可以直接查找定位到某个字的位置

/是查找的意思,+可以表示增加的功能 +/after,增加查找after的功能

[root@localhost em]# vi +/after profile

 

? 关闭文件

? 末行模式:

? :q 退出 没有动过文件

? :wq 保存并退出 动过了,不后悔

? :q! 不保存并退出 动过了,后悔了

? :w 保存

? :w! 强行保存

? :wq --> :x

? ZZ: 保存并退出 不需要冒号,编辑模式

 

全屏编辑器

模式:

编辑模式:按键具有编辑文本功能:默认打开进入编辑模式

输入模式:按键本身意义

末行模式:接受用户命令输入文本操作命令 

在输入模式按ESC退出insert插入模式的界面上,可以按 hjkl上下左右控制光标

 

? 编辑-->输入:

? i: 在当前光标所在字符的前面,转为输入模式;

? a: 在当前光标所在字符的后面,转为输入模式;

 

? o: 在当前光标所在行的下方,新建一行,并转为输入模式;

? O:在当前光标所在行的上方,新建一行,并转为输入模式;

 

? I:在当前光标所在行的行首,转换为输入模式

? A:在当前光标所在行的行尾,转换为输入模式

? 输入-->编辑:

? ESC

? 编辑-->末行:

? :

? 末行-->编辑:

? ESC, ESC   (按两次ESC)

末行模式 shift+冒号,末行模式也可以进行查找,比如 :/after,查找词after

末行模式允许我们对文档输入一些命令,并不会改变文档本身的内容

 

编辑模式

? 移动光标

? 删除&替换单个字符

? 删除命令

? 复制粘贴

? 撤销&重做

 

? 移动光标

? 字符

? h: 左;j: 下;k: 上;l: 右

? 单词

? w: 移至下一个单词的词首

? e: 跳至当前或下一个单词的词尾

? b: 跳至当前或前一个单词的词首

? 行内

? 0: 绝对行首

? ^: 行首的第一个非空白字符

? $: 绝对行尾

? 行间

? G:文章末尾

? 3G:第3行

数字+g,组合键,要快速按,就像打游戏的组合键一样

? gg:文章开头

? 翻屏

? ctrl:f,b

 

? 删除&替换单个字符

? x:删除光标位置字符

? 3x:删除光标开始3个字符

注意是下方没有 insert的编辑模式

20210211-1 Linux基础与应用(中)

? r:替换光标位置字符

? 删除命令 : d ,2d

? dw,dd

d 删除一行,2d删除两行

dw 删除一个单词,dd和d是一样的效果

? 复制粘贴&剪切

? yw,yy

? p

? P

yw就是复制一个单词,和dw相似,单行一个d或者y就可以,加上行数时一定要dd或者yy

? 撤销&重做

? u 撤销

? ctrl+r 重做 撤销的操作

? . 重复上一步的操作

 

末行模式 

? set:设置

? set nu number

? set nonu nonumber

? set readonly (设置只读)

? /:查找

? /after

? n,N (N向上查找,n向下查找)

? ?向上查找

? !:执行命令

? :!ls -l /

? s查找并替换

? s/str1/str2/gi

? /:临近s命令的第一个字符为边界字符:/,@,#

? g:一行内全部替换

? i:忽略大小写

? 范围

? n:行号

? .:当前光标行

? +n:偏移n行

? $:末尾行,$-3

? %:全文文本处理文本处理的几种方法

 

二、文本处理:cut、sort和wc

 

文本处理的几种方法

? cut

? sort

? wc

? awk

 

? cut:显示切割的行数据

? f:选择显示的列

? s:不显示没有分隔符的行

? d:自定义分隔符

[root@localhost ~]# cat grep.txt

aazz12121212aazz

aazz 12121212

aaz 12121212

1212 aazz 1212

aa3zz

aa4zz

aaEzz

aamzz

$aazz

aa1234zz

aaopqzz

现在只想显示第一列,应该怎么做?可以用空格分割

[root@localhost ~]# cut -d ‘ ‘ -f1 grep.txt

aazz12121212aazz

aazz

aaz

1212

aa3zz

aa4zz

aaEzz

aamzz

$aazz

aa1234zz

aaopqzz

如果显示第一至第三列

[root@localhost ~]# cut -d ‘ ‘ -f1-3 grep.txt

如果显示第一 和第三列

[root@localhost ~]# cut -d ‘ ‘ -f1,3 grep.txt

aazz12121212aazz

aazz

aaz

1212 1212

aa3zz

aa4zz

aaEzz

aamzz

$aazz

aa1234zz

aaopqzz

但是,只有一列的也在里面,这样的数据叫做“脏数据”,可以用 -s 排掉,就可以找到有三列的数据

[root@localhost ~]# cut -s -d ‘ ‘ -f1,3 grep.txt

aazz

aaz

1212 1212

 

? sort:排序文件的行

? n:按数值排序

? r:倒序

? t:自定义分隔符

? k:选择排序列

? u:合并相同行

? f:忽略大小写

[root@localhost ~]# cat sort.txt

banana 12

apple 1

orange 8

如果这是一个产品价目表,按产品价格对其进行排序,k2 表示按第 2 列排序

[root@localhost ~]# sort -t ‘ ‘ -k2 -nr sort.txt

banana 12

orange 8

apple 1

如果把n去掉,默认按字典排序

[root@localhost ~]# sort -t ‘ ‘ -k2 -r sort.txt

orange 8

banana 12

apple 1

 

wc word count 单词计数 -l 按行计数

[root@localhost ~]# cat sort.txt

banana 12

apple 1

orange 8

[root@localhost ~]# wc -l sort.txt

3 sort.txt

如果在写脚本文件,想把计算的行数作为一个变量,想去掉 sort.txt

[root@localhost ~]# cat sort.txt | wc -l

3

这样就只显示 3 了,利用管道,先读出文本,把文本传给wc,这样就不会因为命令把名字显示出来了

 

三、文本处理:awk

 

awk

? awk是一个强大的文本分析工具。

? 相对于grep的查找,awk在其对数据分析并生成报告时,显得尤为强大。

? 简单来说awk就是把文件逐行的读入(空格,制表符)默认分隔符将每行切片,切开的部分再进行各种分析处理。

如何在程序里使用定义变量?如果不加引号,执行到空格后,会认为是下一个命令

所以需要把整个的命令用反引号引入

[root@localhost ~]# lines=`cat sort.txt | wc -l`

[root@localhost ~]# echo $lines

3

[root@localhost ~]# cat sort.txt | grep banana

banana 12

 

[root@localhost ~]# cat /etc/passwd

root:x:0:0:root:/root:/bin/bash

bin:x:1:1:bin:/bin:/sbin/nologin

daemon:x:2:2:daemon:/sbin:/sbin/nologin

……

显示所有用户,bin等用户不是登录用户;

root(用户):x:0:0:root(所在组):/root(登录进来的家目录):/bin/bash(/bin/bash指用户一登录进来能够执行的程序 )

 

? awk -F ‘{pattern + action}{filenames}

? 支持自定义分隔符

? 支持正则表达式匹配

? 支持自定义变量,数组 a[1] a[tom] map(key)

? 支持内置变量

? ARGC 命令行参数个数

? ARGV 命令行参数排列

? ENVIRON 支持队列中系统环境变量的使用

? FILENAME awk 浏览的文件名

? FNR 浏览文件的记录数

? FS 设置输入域分隔符,等价于命令行 -F 选项

? NF 浏览记录的域的个数

? NR 已读的记录数

? OFS 输出域分隔符

? ORS 输出记录分隔符

? RS 控制记录分隔符

? 支持函数

? print、split、substr、sub、gsub

? 支持流程控制语句,类C语言

? if、while、do/while、for、break、continue

 

? 只是显示/etc/passwd的账户:CUT

? awk -F‘:‘ ‘{print $1}‘ passwd

[root@localhost etc]# awk -F‘:‘ ‘{print $1}‘ passwd

root

bin

daemon

adm

……

只显示了第一列用户名,awk 可以理解为一段程序,是一个 命令,-F是定义分隔符,以冒号定义分隔符;‘{print $1}‘可以理解为一个程序,方法名大括号中包含程序内容,没有方法名,可以理解为匿名方法;print是它的语法; $1表示 第 1 列

 

? 只是显示/etc/passwd的账户和账户对应的shell,而账户与shell之间以逗号分割,而且在所有行开始前添加列名name,shell,在最后一行添加"blue,/bin/nosh"(cut,sed)

? awk -F‘:‘ ‘BEGIN{print "name,shell"} {print $1 "," $7} END{print"blue,/bin/nosh"}‘ passwd

对应的shell是指最末尾那一行

[root@localhost etc]# awk -F‘:‘ ‘BEGIN{print "name,shell"} {print $1 "," $7} END{print"blue,/bin/nosh"}‘ passwd

name,shell

root,/bin/bash

bin,/sbin/nologin

daemon,/sbin/nologin

adm,/sbin/nologin

lp,/sbin/nologin

……

tcpdump,/sbin/nologin

malakh,/bin/bash

blue,/bin/nosh

相当于制作了一个表头,表头第1列是name,第2列是执行的shell,最后表尾,blue,/bin/nosh

{print $1 "," $7} 读取每一行的时候,以逗号分隔每一行的值,表头是awk内置的一个函数

BEGIN{print "name,shell"} 只在第一行操作

 

? 搜索/etc/passwd有root关键字的所有行

? awk ‘/root/ { print $0}‘ passwd

比如查找所有 root 的关键行,并显示出来

[root@localhost etc]# awk ‘/root/ { print $0}‘ passwd

root:x:0:0:root:/root:/bin/bash

operator:x:11:0:operator:/root:/sbin/nologin

 

? 统计/etc/passwd文件中,每行的行号,每行的列数,对应的完整行内容

? 统计报表:合计每人1月工资,0:manager,1:worker

? Tom 0 2012-12-11 car 3000

? John 1 2013-01-13 bike 1000

? Vivi 1 2013-01-18 car 2800

? Tom 0 2013-01-20 car 2500

? John 1 2013-01-28 bike 3500

? E

? awk ‘{gsub("0","manager",$2);gsub("1","worker",$2);;split($3,month,"-");if(month[2]=="01"){name[$1]+=$5}} ND{for( i in name){print i "\t"name[i]}}‘ awk.txt

现在想统计一月份的,角色是经理的打出m,角色是工人的打出w

[root@localhost ~]# awk ‘{split($3,date,"-");if(date[2]=="01"){name[$1]+=$5};if($2==0){role[$1]="M"}else{role[$1]="W"}} END{for(i in name){print i"\t"name[i]"\t"role[i]}}‘ awk.txt

Tom 2500 M

Vivi 2800 W

John 4500 W

‘{split($3,date,"-")}‘ 日期是第三列,所有$3,拆开split函数,保存到date变量中,切割符是-切割,所以切割成三列,date现在就是一个数组

类似于C的语法 ‘{split($3,date,"-");if(date[2]=="01"){name[$1]+=$5}}’ name[$1]+=$5 定义的数组变量,键是第一列Tom人的名字,值是薪水,第5列 ,+=是因为里面有一些重复数据,把重复数据加到一起了

END{for(i in name){print i"\t"name[i]"\t"role[i]}}‘ awk.txt 最后制作报表,循环打印,\t 制表符

 

? awk ‘{

? split($3,date,"-");

? if(date[2]=="01"){

? name[$1]+=$5

? }

? }

? END{

? for(i in name){

? print i "\t" name[i]}

? }‘ awk.txt

? awk ‘{split($3,date,"-

");if(date[2]=="01"){name[$1]+=$5;if($2=="0"){role[$1]="M"}else{role[$1]=

"W"}}} END{for(i in name){print i "\t" name[i]"\t" role[i]}}‘ awk.txt

 

 

20210211-1 Linux基础与应用(中)

上一篇:开发人员如何成为架构师


下一篇:不止中台:全面的架构演进趋势和方法(5)