Linux-扩展篇
1. 软件包管理
1.1 rpm命令
功能: 用于在Linux系统下对软件包进行安装、卸载、查询、验证、升级等工作。
基本语法
#RPM 查询命令
rpm -qa (功能描述:查询所安装的所有rpm 软件包)
#RPM 卸载命令
rpm -e RPM软件包
rpm -e --nodeps 软件包 (--nodeps 卸载软件时,不检查依赖。这样的话,那些使用该软件包的软件在此之后可能就不能正常工作了。)
#RPM 安装命令
rpm -ivh RPM 包全名
由于软件包比较多,一般都会采取过滤:
rpm -qa | grep rpm软件包
参数 | 说明 |
---|---|
-a | 查询所有的软件包 |
-e | 卸载软件包 |
-i | 安装软件包 |
-p | 查询指定的rpm软件包 |
-q | 查询软件包 |
-v | 显示命令执行过程 |
-U | 升级软件包 |
-l | 显示软件包的文件列表 |
参考示例
# 正常安装软件包
rpm -ivh cockpit-185-2.el8.x86_64.rpm
# 显示系统已安装过的全部RPM软件包
rpm -qa
# 查询某个软件的安装路径
rpm -ql cockpit
# 卸载某个通过RPM软件包安装的服务
rpm -evh cockpit
# 升级某个软件包
rpm -Uvh cockpit-185-2.el8.x86_64.rpm
1.2 yum命令
功能: 用于在Linux系统中基于RPM技术进行软件包的管理工作。
yum
软件仓库及命令能够自动处理软件依赖关系,一次性安装所需全部软件,无需繁琐的操作。
基本语法: yum [选项] [参数] 软件名称
选项说明
选项 | 说明 |
---|---|
-y | 对所有提问都回答“yes” |
参数说明
参数 | 说明 |
---|---|
install | 安装 rpm 软件包 |
update | 更新 rpm 软件包 |
check-update | 检查是否有可用的更新 rpm 软件包 |
remove | 删除指定的 rpm 软件包 |
list | 显示软件包信息 |
clean | 清理 yum 过期的缓存 |
deplist | 显示 yum 软件包的所有依赖关系 |
2. 克隆虚拟机
2.1 克隆
- 从现有虚拟机(关机状态)克隆出新虚拟机,右键选择管理=>克隆
- 点击下一步
- 选择虚拟机中的当前状态
- 选择创建完整克隆
- 设置虚拟机名称及存储位置
- 等待完成…
2.2 开机修改系统相关配置
注意: 使用 root 用户
- 修改
vim /etc/sysconfig/network-scripts/ifcfg-ens33
,修改 IP 地址
- 修改
vim /etc/hostname
,修改主机名
3. Shell编程
3.1 概述
Shell 是一个用 C 语言编写的程序,它是用户使用 Linux 的桥梁。Shell 既是一种命令语言,又是一种程序设计语言。
Shell 编程跟 JavaScript、php 编程一样,只要有一个能编写代码的文本编辑器和一个能解释执行的脚本解释器就可以了。
Linux 的 Shell 种类众多,常见的有:
- Bourne Shell(/usr/bin/sh或/bin/sh)
- Bourne Again Shell(/bin/bash)
- C Shell(/usr/bin/csh)
- K Shell(/usr/bin/ksh)
- Shell for Root(/sbin/sh)
……
sh/bash/csh/Tcsh/ksh/pdksh等shell的区别:
- sh(全称 Bourne Shell): 是UNIX最初使用的 shell,而且在每种 UNIX 上都可以使用。
- Bourne Shell: 在 shell 编程方面相当优秀,但在处理与用户的交互方面做得不如其他几种 shell。
- bash(全称 Bourne Again Shell): LinuxOS 默认的,它是 Bourne Shell 的扩展。 与 Bourne Shell 完全兼容,并且在 Bourne Shell 的基础上增加了很多特性。可以提供命令补全,命令编辑和命令历史等功能。它还包含了很多 C Shell 和 Korn Shell 中的优点,有灵活和强大的编辑接口,同时又很友好的用户界面。
- csh(全称 C Shell): 是一种比 Bourne Shell更适合的变种 Shell,它的语法与 C 语言很相似。
- Tcsh: 是 Linux 提供的 C Shell 的一个扩展版本。Tcsh 包括命令行编辑,可编程单词补全,拼写校正,历史命令替换,作业控制和类似 C 语言的语法,他不仅和 Bash Shell 提示符兼容,而且还提供比 Bash Shell 更多的提示符参数。
- ksh(全称 Korn Shell): 集合了 C Shell 和 Bourne Shell 的优点并且和 Bourne Shell 完全兼容。
- pdksh: 是 Linux 系统提供的 ksh 的扩展。pdksh 支持人物控制,可以在命令行上挂起,后台执行,唤醒或终止程序。
Linux提供的Shell解析器
[root@localhost bin]# cat /etc/shells
/bin/sh
/bin/bash
/usr/bin/sh
/usr/bin/bash
/bin/tcsh
/bin/csh
bash 和 sh 的关系
[root@localhost bin]# ll | grep bash
-rwxr-xr-x. 1 root root 964536 4月 1 2020 bash
lrwxrwxrwx. 1 root root 10 9月 13 14:53 bashbug -> bashbug-64
-rwxr-xr-x. 1 root root 6964 4月 1 2020 bashbug-64
lrwxrwxrwx. 1 root root 4 9月 13 14:53 sh -> bash
Centos 默认的解析器是 bash
[root@localhost bin]# echo $SHELL
/bin/bash
3.2 编写shell脚本
脚本以 #!/bin/bash
开头(指定解析器)
#!
告诉系统其后路径所指定的程序即是解释此脚本文件的 Shell 程序。
打开文本编辑器(可以使用 vi/vim
命令来创建文件),新建一个文件 helloworld.sh
,扩展名为 sh
(sh代表shell),扩展名并不影响脚本执行。
[root@localhost scripts]$ touch helloworld.sh
[root@localhost scripts]$ vim helloworld.sh
// 在 helloworld.sh 中输入如下内容
#!/bin/bash
echo "Helloworld"
#!
是一个约定的标记,它告诉系统这个脚本需要什么解释器来执行,即使用哪一种 Shell。
echo
命令用于向窗口输出文本。
3.3 脚本的常用执行方式
-
采用 bash 或 sh+脚本的相对路径或绝对路径(不用赋予脚本+x 权限)
- sh+脚本的相对路径
[root@localhost scripts]$ sh ./helloworld.sh Helloworld
- sh+脚本的绝对路径
[root@localhost scripts]$ sh /root/scripts/helloworld.sh Helloworld
- bash+脚本的相对路径
[root@localhost scripts]$ bash ./helloworld.sh Helloworld
- bash+脚本的绝对路径
[root@localhost scripts]$ bash /root/scripts/helloworld.sh Helloworld
这种执行方法,本质是 bash 解析器帮你执行脚本,所以脚本本身不需要执权限。
-
采用输入脚本的绝对路径或相对路径执行脚本(必须具有可执行权限+x)
- 首先要赋予 helloworld.sh 脚本的+x 权限
[root@localhost scripts]$ chmod +x helloworld.sh
- 相对路径
[root@localhost scripts]$ ./helloworld.sh Helloworld
- 绝对路径
[root@Demo shells]$ /root/scripts/helloworld.sh Helloworld
这种执行方法,本质是脚本需要自己执行,所以需要执行权限。
-
在脚本的路径前加上 “.” 或者 source
- 编写以下脚本
[root@localhost scripts]$ cat test.sh #!/bin/bash A=5 echo $A
- 分别用 sh,bash,./ 和 . 的方式来执行
[root@localhost scripts]$ bash test.sh 5 [root@localhost scripts]$ sh test.sh 5 [root@localhost scripts]$ ./test.sh 5 [root@localhost scripts]$ . test.sh 5 [root@localhost scripts]$ source test.sh 5 [root@localhost scripts]$ source /root/scripts/test.sh 5
前两种方式都是在当前 shell 中打开一个子 shell 来执行脚本内容,当脚本内容结束,则子 shell 关闭,回到父 shell 中。
第三种使用在脚本路径前加 “.”
或者 source
的方式,可以使脚本内容在当前 shell 里执行,而无需打开子 shell!这也是为什么我们每次要修改完 /etc/profile
文件以后,需要 source 一下的原因。
打开子shell 与不打开子shell 的区别就在于,环境变量的继承关系,如在子 shell 中设置的当前变量,父 shell 是不可见的。
4. 变量
4.1 常用系统变量
$HOME
、$PWD
、$SHELL
、$USER
等
查看系统变量的值
[root@localhost scripts]# echo $HOME
/root
显示当前 Shell 中所有变量
$ set
4.2 自定义变量
定义基本语法:
变量名=变量值(注意,=号前后不能有空格)
变量名的命名须遵循规则
- 命名只能使用
英文字母,数字和下划线
,首个字符不能以数字开头。环境变量名建议大写 - 中间不能有空格,可以使用下划线
_
- 不能使用标点符号
- 不能使用bash里的关键字(可用help命令查看保留关键字)
- 变量的值如果有空格,需要使用
双引号或单引号
括起来
在bash 中,变量默认类型都是字符串类型,无法直接进行数值运算,但可以通过
$((1+6))
或$[1+6]
进行运算
使用
export 变量名
可把变量提升为全局环境变量,可供其他 Shell 程序使用
使用变量
使用一个定义过的变量,只要在变量名前面加美元符号即可,如:
your_name="haha"
echo $your_name
echo ${your_name}
变量名外面的花括号是可选的,加不加都行,加花括号是为了帮助解释器识别变量的边界(建议加上,这是好的编程习惯)
只读变量
使用 readonly 命令可以将变量定义为只读变量,只读变量的值不能被改变。如:
#!/bin/bash
myUrl="https://www.google.com"
readonly myUrl
myUrl="https://www.runoob.com"
运行脚本报错:/bin/sh: NAME: This variable is read only.
删除变量
使用 unset
命令可以删除变量。语法:
unset variable_name
变量被删除后不能再次使用。unset 命令不能删除只读变量。如下参考示例无任何输出
#!/bin/sh
myUrl="https://www.runoob.com"
unset myUrl
echo $myUrl
变量类型
-
局部变量
局部变量在脚本或命令中定义,仅在当前
shell
实例中有效,其他shell启动的程序不能访问局部变量。 -
环境变量
所有的程序,包括
shell
启动的程序,都能访问环境变量,有些程序需要环境变量来保证其正常运行。必要的时候shell
脚本也可以定义环境变量。 -
shell变量
shell
变量是由shell
程序设置的特殊变量。shell
变量中有一部分是环境变量,有一部分是局部变量,这些变量保证了shell
的正常运行
参考示例
# 定义变量 A
[root@localhost scripts]$ A=5
[root@localhost scripts]$ echo $A
5
# 给变量 A 重新赋值
[root@localhost scripts]$ A=8
[root@localhost scripts]$ echo $A
8
# 撤销变量 A
[root@localhost scripts]$ unset A
[root@localhost scripts]$ echo $A
# 声明静态的变量 B=2,不能 unset
[root@localhost scripts]$ readonly B=2
[root@localhost scripts]$ echo $B
2
[root@localhost scripts]$ B=9
-bash: B: readonly variable
# 在 bash 中,变量默认类型都是字符串类型,无法直接进行数值运算
[root@localhost scripts]$ C=1+2
[root@localhost scripts]$ echo $C
1+2
# 变量的值如果有空格,需要使用双引号或单引号括起来
[root@localhost scripts]$ D=I love you
-bash: world: command not found
[root@localhost scripts]$ D="I love you"
[root@localhost scripts]$ echo $D
I love you
# 可把变量提升为全局环境变量,可供其他 Shell 程序使用
# 在 helloworld.sh 文件中增加 echo $B
[root@localhost scripts]$ vim helloworld.sh
#!/bin/bash
echo "helloworld"
echo $B
[root@localhost scripts]$ ./helloworld.sh
Helloworld
# 发现并没有打印输出变量 B 的值
# 使用 export 变量名
[root@localhost scripts]$ export B
[root@localhost scripts]$ ./helloworld.sh
helloworld
2
4.3 特殊变量
-
$n
功能: n 为数字,
$0
代表该脚本名称,$1~$9
代表第1到第9个参数,10以上的参数用大括号包含,如${10}
参考示例
[root@localhost scripts]$ touch parameter.sh [root@localhost scripts]$ vim parameter.sh #!/bin/bash echo '==========$n==========' echo $0 echo $1 echo $2 [root@localhost scripts]$ chmod 777 parameter.sh [root@localhost scripts]$ ./parameter.sh cls xz ==========$n========== ./parameter.sh cls xz
-
$#
功能: 获取所有
输入参数个数
,常用于循环、判断参数的个数是否正确以及加强脚本的健壮性参考示例
[root@localhost scripts]$ vim parameter.sh #!/bin/bash echo '==========$n==========' echo $0 echo $1 echo $2 echo '==========$#==========' echo $# [root@localhost scripts]$ chmod 777 parameter.sh [root@localhost scripts]$ ./parameter.sh cls xz ==========$n========== ./parameter.sh cls xz ==========$#========== 2
-
$*、$@
功能
$*
: 代表命令行中所有的参数,$*
把所有的参数看成一个整体
$@
:代表命令行中所有的参数,$@
把每个参数区分对待(类似于数组)参考示例
[root@localhost scripts]$ vim parameter.sh #!/bin/bash echo '==========$n==========' echo $0 echo $1 echo $2 echo '==========$#==========' echo $# echo '==========$*==========' echo $* echo '==========$@==========' echo $@ [root@localhost scripts]$ ./parameter.sh a b c d e f g ==========$n========== ./parameter.sh ab ==========$#========== 7 ==========$*========== a b c d e f g ==========$@========== a b c d e f g
-
$?
功能: 最后一次执行的命令的返回状态。如果这个变量的值为0,证明上一个命令正确执行;如果这个变量的值为非0(具体是哪个数,由命令自己来决定),则证明上一个命令执行不正确了。
参考示例
#判断hello world.sh是否执行 [root@localhost scripts]$ ./helloworld.sh hello world [root@localhost scripts]$ echo $? 0
5. 运算符
基本语法: $((运算式))
或 '$[运算式]
参考示例
[root@localhost scripts]# vim add.sh
#!/bin/bash
echo $[$1+$2]
[root@localhost scripts]# bash ./add.sh 25 89
114
#如果传入的参数是字符串abc之类的话,shell无法将其解析为整数,就会被视为0
[root@localhost scripts]# bash ./add.sh 25 abc
25
6. 条件判断
-
基本语法
-
test condition
-
[ condition ]
(注意 condition 前后要有空格)
注意: 条件非空即为true,
[ hahaha ]
返回true,[ ]
返回false。 -
-
常用判断条件
-
字符串之间的比较
符号 说明 =
判断相等 !=
判断不等 -
两个整数之间比较
符号 说明 -eq
等于(equal) -ne
不等于(not equal) -lt
小于(less than) -le
小于等于(less equal) -gt
大于(greater than) -ge
大于等于(greater equal) -
按照文件权限进行判断
符号 说明 -r
有读的权限(read) -w
有写的权限(write) -x
有执行的权限(execute) -
按照文件类型进行判断
符号 说明 -e
文件存在(existence) -f
文件存在并且是一个常规的文件(file) -d
文件存在并且是一个目录(directory)
-
参考示例
# 23 是否大于等于22
[root@localhost scripts]$ [ 23 -ge 22 ]
[root@localhost scripts]$ echo $?
0
# helloworld.sh 是否具有写权限
[root@localhost scripts]$ [ -w helloworld.sh ]
[root@localhost scripts]$ echo $?
0
# /home/user/cls.txt 目录中的文件是否存在
[root@localhost scripts]$ [ -e /home/user/cls.txt ]
[root@localhost scripts]$ echo $?
1
#多条件判断(三目运算符:&& 表示前一条命令执行成功时,才执行后一条命令,|| 表示上一条命令执行失败后,才执行下一条命令)
[root@localhost scripts]$ [ user ] && echo OK || echo notOK
OK
[root@localhost scripts]$ [ ] && echo OK || echo notOK
notOK
7. 流程控制
7.1 if判断
-
基本语法
注意!!!
①[ 条件判断式 ]
中括号和条件判断式之间必须有空格
②if
后要有空格- 单分支
if [ 条件判断式 ];then 程序 fi 或者----------------------- if [ 条件判断式] then 程序 fi
- 多分支
if [ 条件判断式 ] then 程序 elif [ 条件判断式 ] then 程序 else 程序 fi
-
参考示例
输入一个数字,如果是
1
,则输出banzhang zhen shuai
,如果是2
,则输出cls zhen mei
,如果是其它,什么也不输出。[root@localhost scripts]$ touch if.sh [root@localhost scripts]$ vim if.sh #!/bin/bash if [ $1 -eq 1 ] then echo "banzhang zhen shuai" elif [ $1 -eq 2 ] then echo "cls zhen mei" fi [root@localhost scripts]$ chmod 777 if.sh [root@localhost scripts]$ ./if.sh 1 banzhang zhen shuai
7.2 case语句
-
基本语法
注意!!!
(1)case 行尾
必须为单词in
,每一个模式匹配必须以右括号)
结束
(2)双分号;;
表示命令序列结束,相当于 java 中的break
(3)最后的*)
表示默认模式,相当于 java 中的defaultcase $变量名in "值1") 如果变量的值等于值1,则执行程序1 ;; "值2") 如果变量的值等于值2,则执行程序2 ;; …省略其他分支… *) 如果变量的值都不是以上的值,则执行此程序 ;; esac
-
参考示例
输入一个数字,如果是
1
,则输出banzhang
,如果是2
,则输出cls
,如果是其它
,输出renyao
。[root@localhost scripts]$ touch case.sh [root@localhost scripts]$ vim case.sh !/bin/bash case $1 in "1") echo "banzhang" ;; "2") echo "cls" ;; *) echo "renyao" ;; esac [root@localhost scripts]$ chmod 777 case.sh [root@localhost scripts]$ ./case.sh 1 1
7.3 for循环
-
基本语法1
for (( 初始值;循环控制条件;变量变化)) do 程序 done
-
参考示例
从1 加到100
[root@localhost scripts]$ touch for1.sh [root@localhost scripts]$ vim for1.sh #!/bin/bash sum=0 for((i=0;i<=100;i++)) do sum=$[$sum+$i] done echo $sum [root@localhost scripts]$ chmod 777 for1.sh [root@localhost scripts]$ ./for1.sh 5050
-
基本语法2
for 变量in 值1 值2 值3… do 程序 done
-
参考示例
- 打印所有输入参数
[root@localhost scripts]$ touch for2.sh [root@localhost scripts]$ vim for2.sh #!/bin/bash #打印数字 for i in cls mly wls do echo "ban zhang love $i" done [root@localhost scripts]$ chmod 777 for2.sh [root@localhost scripts]$ ./for2.sh ban zhang love cls ban zhang love mly ban zhang love wls
-
比较 $* 和 $@ 区别
$*
和$@
都表示传递给函数或脚本的所有参数,不被双引号“”
包含时,都以$1 $2 …$n
的形式输出所有参数。[root@localhost scripts]$ touch for3.sh [root@localhost scripts]$ vim for3.sh #!/bin/bash echo '=============$*=============' for i in $* do echo "ban zhang love $i" done echo '=============$@=============' for j in $@ do echo "ban zhang love $j" done [root@localhost scripts]$ chmod 777 for3.sh [root@localhost scripts]$ ./for3.sh cls mly wls =============$*============= banzhang love cls banzhang love mly banzhang love wls =============$@============= banzhang love cls banzhang love mly banzhang love wls
当它们被双引号
“”
包含时,$*
会将所有的参数作为一个整体,以"$1 $2 …$n"
的形式输出所有参数;$@
会将各个参数分开,以"$1” “$2”…“$n"
的形式输出所有参数。[root@localhost scripts]$ vim for4.sh #!/bin/bash echo '=============$*=============' for i in "$*" #$*中的所有参数看成是一个整体,所以这个for 循环只会循环一次 do echo "ban zhang love $i" done echo '=============$@=============' for j in "$@" #$@中的每个参数都看成是独立的,所以“$@”中有几个参数,就会循环几次 do echo "ban zhang love $j" done [root@localhost scripts]$ chmod 777 for4.sh [root@localhost scripts]$ ./for4.sh cls mly wls =============$*============= banzhang love cls mly wls =============$@============= banzhang love cls banzhang love mly banzhang love wls
7.4 while 循环
- 基本语法
while [ 条件判断式] do 程序 done
- 参考示例
[root@localhost scripts]$ touch while.sh [root@localhost scripts]$ vim while.sh #!/bin/bash sum=0 i=1 while [ $i -le 100 ] do sum=$[$sum+$i] i=$[$i+1] done echo $sum [root@localhost scripts]$ chmod 777 while.sh [root@localhost scripts]$ ./while.sh 5050
8. read 读取控制台输入
-
基本语法
read (选项) (参数)
- 选项:
- -p:指定读取值时的提示符;
- -t:指定读取值时等待的时间(秒)如果-t 不加表示一直等待
- 参数
- 变量:指定读取值的变量名
- 选项:
-
参考示例
提示7 秒内,读取控制台输入的名称
[root@localhost scripts]$ touch read.sh [root@localhost scripts]$ vim read.sh #!/bin/bash read -t 7 -p "Enter your name in 7 seconds :" NN echo $NN [root@localhost scripts]$ ./read.sh Enter your name in 7 seconds : koukk koukk
9. 函数
9.1 系统函数
9.1.1 basename
-
基本语法
basename [string / pathname] [suffix]
功能描述:
basename
命令会删掉所有的前缀包括最后一个(‘/’)字符,然后将字符串显示出来。选项:
suffix
为后缀,如果suffix
被指定了,basename
会将pathname
或string
中的suffix
去掉。 -
参考示例
截取该
/home/user/banzhang.txt
路径的文件名称。[root@localhost scripts]$ basename /home/user/banzhang.txt banzhang.txt [root@localhost scripts]$ basename /home/user/banzhang.txt .txt banzhang
9.1.2 dirname
-
基本语法
dirname 文件绝对路径
功能描述:从给定的包含绝对路径的文件名中去除文件名(非目录的部分),然后返回剩下的路径(目录的部分)
dirname
可以理解为取文件路径的绝对路径名称 -
参考示例
获取
banzhang.txt
文件的路径[root@localhost scripts]$ dirname /home/user/banzhang.txt /home/user
9.2 自定义函数
(1)必须在调用函数地方之前,先声明函数,shell 脚本是逐行运行。不会像其它语言一样先编译。
(2)函数返回值,只能通过$?
系统变量获得,可以显示加return
返回,如果不加,将以最后一条命令运行结果,作为返回值。return
后跟数值n
(0-255)
-
基本语法
[ function ] funname[()] { Action; [return int;] }
-
参考示例
计算两个输入参数的和。
[root@localhost scripts]$ touch fun.sh [root@localhost scripts]$ vim fun.sh #!/bin/bash function add(){ s=$[$1+$2] echo $s } read -p "Please input the number1: " n1; read -p "Please input the number2: " n2; sum=$(add $n1 $n2); echo "和:"$sum echo "喝的平方:"$[$sum * $sum] [root@localhost scripts]$ chmod 777 fun.sh [root@localhost scripts]$ ./fun.sh Please input the number1: 156 Please input the number2: 237 和:393 和的平方:154449
10. 正则表达式
正则表达式使用单个字符串来描述、匹配一系列符合某个语法规则的字符串。在很多文本编辑器里,正则表达式通常被用来检索、替换那些符合某个模式的文本。在 Linux 中,grep,sed,awk 等文本处理工具都支持通过正则表达式进行模式匹配。
常用的特殊字符
^
匹配一行的开头
[root@localhost scripts]$ cat /etc/passwd | grep ^a
# 会匹配出所有以 a 开头的行
$
匹配一行的结束
[root@localhost scripts]$ cat /etc/passwd | grep t$
# 会匹配出所有以 t 结尾的行
.
匹配一个任意的字符
[root@localhost scripts]$ cat /etc/passwd | grep r..t
# 会匹配包含 rabt,rbbt,rxdt,root 等的所有行
*
不单独使用,他和上一个字符连用,表示匹配上一个字符 0 次或 多次
[root@localhost scripts]$ cat /etc/passwd | grep ro*t
# 会匹配 rt, rot, root, rooot, roooot 等所有行
.*
表示任意字符匹配任意多次,包含空字符串,*
可能匹配 0次
?
不单独使用,他和上一个字符连用,表示匹配上一个字符 0 次或 1 次
+
不单独使用,他和上一个字符连用,表示匹配上一个字符 1 次或 多次
{n}
匹配前一个字符 n 次
{n, }
至少匹配前一个字符 n 次
{n, m}
至少匹配前一个字符 n 次,至多匹配 m 次
字符区间(中括号): [ ]
- [] 表示匹配某个范围内的一个字符
- [6,8] 或 [68] ------ 匹配 6 或者 8
- [0-9] ------ 匹配一个 0-9 的数字
- [0-9]* ------ 匹配任意长度的数字字符串
- [0-9]{9} ------ 匹配9个长度的数字字符串
- [a-z] ------匹配一个 a-z 之间的字符
- [a-z]* ------ 匹配任意长度的字母字符串
- [a-z]{3,} ------ 匹配至少3个长度长度的字母字符串
- [a-c, e-f]{3,5} ----- 匹配至少3次,至多5次的 a-c 或者 e-f 之间的任意字符
\
表示转义,并不会单独使用。由于所有特殊字符都有其特定匹配模式,当我们想匹配某一特殊字符本身时(例如,我想找出所有包含 ‘$’ 的行),就会碰到困难。此时我们就要将转义字符和特殊字符连用,来表示特殊字符本身。
[root@localhost scripts]$ cat /etc/passwd | grep ‘a\$b’
# 就会匹配所有包含 a$b 的行。注意需要使用单引号将表达式引起来
11. 文本处理工具
11.1 cut
cut 的工作就是“剪”,具体的说就是在文件中负责剪切数据用的。cut 命令从文件的每一行剪切字节、字符和字段并将这些字节、字符和字段输出。
-
基本语法:
cut [选项参数] filename
选项参数 说明 -f 列号,提取第几列 -d 分隔符,按照指定分隔符分割列,默认是制表符“\t” -c 按字符进行切割后加加n 表示取第几列比如-c 1 -
参考示例
- 数据准备
[root@localhost scripts]$ touch cut.txt [root@localhost scripts]$ vim cut.txt dong shen guan zhen wo wo lai lai le le
- 切割 cut.txt 第一列
[root@localhost scripts]$ cut -d " " -f 1 cut.txt dong guan wo lai le
- 切割 cut.txt 第二、三列
[root@localhost scripts]$ cut -d " " -f 2,3 cut.txt shen zhen wo lai le
- 在 cut.txt 文件中切割出 guan
[root@localhost scripts]$ cat cut.txt |grep guan | cut -d " " -f 1 guan
- 选取系统 PATH 变量值,第 2 个
“:”
开始后的所有路径:
[root@localhost scripts]$ echo $PATH /usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/atguigu/.local/bin:/home/atguigu/bin [root@localhost scripts]$ echo $PATH | cut -d ":" -f 3- /usr/local/sbin:/usr/sbin:/home/atguigu/.local/bin:/home/atguigu/bin
- 切割 ifconfig 后打印的 IP 地址
[root@localhost scripts]$ ifconfig ens33 | grep netmask | cut -d " " -f 10 192.168.111.101
11.2 awk
AWK 是一种处理文本文件的语言,是一个强大的文本分析工具,把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行分析处理。
基本语法: awk [选项参数] ‘/pattern1/{action1} /pattern2/{action2}...’ filename
pattern:表示 awk 在数据中查找的内容,就是匹配模式,包括正则表达式
action:在找到匹配内容时所执行的一系列命令
只有匹配了 pattern 的行才会执行 action
选项参数 | 说明 |
---|---|
-F | 指定输入文件分隔符 |
-v | 赋值一个用户定义变量 |
-
基本使用
-
log.txt文本内容
2 this is a test 3 Do you like awk This's a test 10 There are orange,apple,mongo
-
用法一:
awk '{[pattern] action}' {filenames} 行匹配语句 awk ‘’
只能用单引号每行按空格或TAB分割,输出文本中的1、4项
$ awk '{print $1,$4}' log.txt 2 a 3 like This's 10 orange,apple,mongo
格式化输出
$ awk '{printf "%-8s %-10s\n",$1,$4}' log.txt 2 a 3 like This's 10 orange,apple,mongo
-
用法二:
awk -F
-F相当于内置变量FS, 指定分割字符使用","分割
$ awk -F, '{print $1,$2}' log.txt 2 this is a test 3 Do you like awk This's a test 10 There are orange apple
使用多个分隔符。先使用空格分割,然后对分割结果再使用 “,” 分割
$ awk -F '[ ,]' '{print $1,$2,$5}' log.txt 2 this test 3 Do awk This's a 10 There apple
-
用法三:
awk -v
设置变量$ awk -va=1 '{print $1,$1+a}' log.txt 2 3 3 4 This's 1 10 11
$ awk -va=1 '{print $1,$1+a}' log.txt 2 3 3 4 This's 1 10 11
-
用法四:
awk -f {awk脚本} {文件名}
$ awk -f cal.awk log.txt
-
-
运算符
运算符 说明 = += -= *= /= %= ^= **= 赋值 ?: C条件表达式 && 逻辑与 ~ 和 !~ 匹配正则表达式和不匹配正则表达式 < <= > >= != == 关系运算符 空格 连接 ! + - 逻辑非,一元加和减 ^ *** 求幂 ++ – 增加或减少,作为前缀或后缀 参考示例
过滤第一列大于2的行
$ awk '$1>2' log.txt # 输出 3 Do you like awk This's a test 10 There are orange,apple,mongo
过滤第一列等于2的行
$ awk '$1==2 {print $1,$3}' log.txt # 输出 2 is
过滤第一列大于2并且第二列等于’Do’的行
$ awk '$1>2 && $2=="Do" {print $1,$2,$3}' log.txt # 输出 3 Do you
-
内置变量
变量 说明 ARGC 命令行参数的数目 ARGIND 命令行中当前文件的位置(从0开始算) ARGV 包含命令行参数的数组 FILENAME 当前文件名 FNR 各文件分别计数的行号 FS 字段分隔符(默认是任何空格) NF 一条记录的字段的数目 NR 已经读出的记录数,就是行号,从1开始 OFS 输出字段分隔符,默认值与输入字段分隔符一致。 ORS 输出记录分隔符(默认值是一个换行符) RS 记录分隔符(默认是一个换行符) 参考示例
$ awk 'BEGIN{printf "%4s %4s %4s %4s %4s %4s %4s %4s %4s\n","FILENAME","ARGC","FNR","FS","NF","NR","OFS","ORS","RS";printf "---------------------------------------------\n"} {printf "%4s %4s %4s %4s %4s %4s %4s %4s %4s\n",FILENAME,ARGC,FNR,FS,NF,NR,OFS,ORS,RS}' log.txt FILENAME ARGC FNR FS NF NR OFS ORS RS --------------------------------------------- log.txt 2 1 5 1 log.txt 2 2 5 2 log.txt 2 3 3 3 log.txt 2 4 4 4
$ awk -F\' 'BEGIN{printf "%4s %4s %4s %4s %4s %4s %4s %4s %4s\n","FILENAME","ARGC","FNR","FS","NF","NR","OFS","ORS","RS";printf "---------------------------------------------\n"} {printf "%4s %4s %4s %4s %4s %4s %4s %4s %4s\n",FILENAME,ARGC,FNR,FS,NF,NR,OFS,ORS,RS}' log.txt FILENAME ARGC FNR FS NF NR OFS ORS RS --------------------------------------------- log.txt 2 1 ' 1 1 log.txt 2 2 ' 1 2 log.txt 2 3 ' 2 3 log.txt 2 4 ' 1 4
输出顺序号 NR, 匹配文本行号
$ awk '{print NR,FNR,$1,$2,$3}' log.txt 1 1 2 this is 2 2 3 Do you 3 3 This's a test 4 4 10 There are
指定输出分割符
$ awk '{print $1,$2,$5}' OFS=" $ " log.txt 2 $ this $ test 3 $ Do $ awk This's $ a $ 10 $ There $
使用正则,字符串匹配,输出第二列包含 “th”,并打印第二列与第四列
$ awk '$2 ~ /th/ {print $2,$4}' log.txt # ~ 表示模式开始。// 中是模式。 this a # 输出包含 "re" 的行 $ awk '/re/ ' log.txt 10 There are orange,apple,mongo
-
awk脚本
BEGIN{ 这里面放的是执行前的语句 } END {这里面放的是处理完所有的行后要执行的语句 }
参考示例
有这么一个文件(成绩表):
$ 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
awk 脚本如下
$ 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