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 克隆

  1. 从现有虚拟机(关机状态)克隆出新虚拟机,右键选择管理=>克隆 在这里插入图片描述
  2. 点击下一步
    在这里插入图片描述
  3. 选择虚拟机中的当前状态
    在这里插入图片描述
  4. 选择创建完整克隆
    在这里插入图片描述
  5. 设置虚拟机名称及存储位置
    在这里插入图片描述
  6. 等待完成…

2.2 开机修改系统相关配置

注意: 使用 root 用户

  1. 修改vim /etc/sysconfig/network-scripts/ifcfg-ens33,修改 IP 地址
    在这里插入图片描述
  2. 修改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 41 2020 bash
lrwxrwxrwx. 1 root root         10 913 14:53 bashbug -> bashbug-64
-rwxr-xr-x. 1 root root       6964 41 2020 bashbug-64
lrwxrwxrwx. 1 root root          4 913 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 特殊变量

  1. $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
    
  2. $#

    功能: 获取所有输入参数个数,常用于循环、判断参数的个数是否正确以及加强脚本的健壮性

    参考示例

    [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
    
  3. $*、$@

    功能
    $*: 代表命令行中所有的参数,$*把所有的参数看成一个整体
    $@:代表命令行中所有的参数,$@把每个参数区分对待(类似于数组)

    参考示例

    [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
    
  4. $?

    功能: 最后一次执行的命令的返回状态。如果这个变量的值为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. 条件判断

  • 基本语法

    1. test condition

    2. [ 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判断

  1. 基本语法

    注意!!!
    [ 条件判断式 ] 中括号和条件判断式之间必须有空格
    if 后要有空格

    • 单分支
    	if [ 条件判断式 ];then
    		程序
    	fi
    	或者-----------------------
    	if [ 条件判断式]
    	then
    		程序
    	fi
    
    • 多分支
    	if [ 条件判断式 ]
    	then
    		程序
    	elif [ 条件判断式 ]
    	then
    		程序
    	else
    		程序
    	fi
    
  2. 参考示例

    输入一个数字,如果是 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. 基本语法

    注意!!!
    (1)case 行尾必须为单词 in,每一个模式匹配必须以右括号 ) 结束
    (2)双分号 ;; 表示命令序列结束,相当于 java 中的break
    (3)最后的 *) 表示默认模式,相当于 java 中的default

    case $变量名in
    "值1")
    	如果变量的值等于值1,则执行程序1
    ;;
    "值2")
    	如果变量的值等于值2,则执行程序2
    ;;
    	…省略其他分支…
    *)
    	如果变量的值都不是以上的值,则执行此程序
    ;;
    esac
    
  2. 参考示例

    输入一个数字,如果是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. 基本语法1

    for (( 初始值;循环控制条件;变量变化))
    do
    	程序
    done
    
  2. 参考示例

    从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
    
  3. 基本语法2

    for 变量in 值1 值2 值3…
    do
    	程序
    done
    
  4. 参考示例

    1. 打印所有输入参数
    	[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. 比较 $* 和 $@ 区别

      $*$@ 都表示传递给函数或脚本的所有参数,不被双引号“”包含时,都以 $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 循环

  1. 基本语法
    while [ 条件判断式]
    do
    	程序
    done
    
  2. 参考示例
    [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 读取控制台输入

  1. 基本语法

    read (选项) (参数)
    
    • 选项:
      • -p:指定读取值时的提示符;
      • -t:指定读取值时等待的时间(秒)如果-t 不加表示一直等待
    • 参数
      • 变量:指定读取值的变量名
  2. 参考示例

    提示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

  1. 基本语法

    basename [string / pathname] [suffix]

    功能描述:basename 命令会删掉所有的前缀包括最后一个(‘/’)字符,然后将字符串显示出来。

    选项:suffix 为后缀,如果 suffix 被指定了,basename 会将 pathnamestring 中的 suffix 去掉。

  2. 参考示例

    截取该 /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

  1. 基本语法

    dirname 文件绝对路径

    功能描述:从给定的包含绝对路径的文件名中去除文件名(非目录的部分),然后返回剩下的路径(目录的部分)

    dirname 可以理解为取文件路径的绝对路径名称

  2. 参考示例

    获取 banzhang.txt 文件的路径

    [root@localhost scripts]$ dirname /home/user/banzhang.txt
    /home/user
    

9.2 自定义函数

(1)必须在调用函数地方之前,先声明函数,shell 脚本是逐行运行。不会像其它语言一样先编译。
(2)函数返回值,只能通过 $? 系统变量获得,可以显示加 return 返回,如果不加,将以最后一条命令运行结果,作为返回值。return 后跟数值 n(0-255)

  1. 基本语法

    [ function ] funname[()]
    {
    	Action;
    	[return int;]
    }
    
  2. 参考示例

    计算两个输入参数的和。

    [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 命令从文件的每一行剪切字节、字符和字段并将这些字节、字符和字段输出。

  1. 基本语法: cut [选项参数] filename

    选项参数说明
    -f列号,提取第几列
    -d分隔符,按照指定分隔符分割列,默认是制表符“\t”
    -c按字符进行切割后加加n 表示取第几列比如-c 1
  2. 参考示例

    • 数据准备
    	[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赋值一个用户定义变量
  1. 基本使用

    • 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
      
  2. 运算符

    运算符说明
    = += -= *= /= %= ^= **=赋值
    ?: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
    
  3. 内置变量

    变量说明
    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
    
  4. 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
    
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值