grep、正则表达式、bash基础特性(运算) 2020/1/3

grep:文本处理三剑客中重要一员:grp ,sed ,awk

grep:文本过滤工具(基于模式:pattern实现过滤)

      grep,egrep,fgrep

sed:strean editer ,文本编辑工具

awk:Linux上的实现为gawk,文本报告生成器

 

grep:global search regular expression and print out the line

作用:文本搜索工具,根据用户指定的‘模式’对目标文本逐行进行匹配检查,打印匹配到的行

模式:有正则表达式字符及文本字符所编写的过滤条件

regexp:正则表达式:由一类特殊字符及文本字符所编写的模式,其中有些字符不表示字面意义而表示控制或者通配

   正则表达式分两类:

  1. 基本正则表达式:BRE
  2. 扩展的正则表达式:ERE

grep默认仅支持基本正则表达式,要使用扩展正则表达式要使用egrep或者grep -E

fgrep:fast grep 快速grep也可以用grep -F

正则表达式引擎

grep [OPTIONS] PATTERN [FILE...]

选项:

--color=auto 对匹配到的文本着色高亮显示

-v 反向选择,显示不能被pattern匹配的行

-i 匹配时忽略字符大小写

-o 仅显示匹配到的字符串

-q 静默模式

-A # 显示匹配行以及后#行

-B # 显示匹配行以及前#行

-C # 显示匹配行前后各#行

 

基本正则表达式元字符:(字符不表示字面意义,而表示通配或者控制)

     字符匹配:

          .: 匹配任意单个字符

         [ ]:  匹配指定范围内的单个字符

         [^]:  匹配指定范围    外的任意单个字符

[:alnum:]数字+字母  [:alpha:]大小写字母  [:blank:]  [:cntrl:]

       [:digit:]数字  [:graph:]  [:lower:]小写字母  [:print:]

       [:punct:]标点符号  [:space:]空格  [:upper:]大写字母  [:xdigit:]

     匹配次数:用在要指定次数的字符后面,用于指定前面的字符要出现的次数:

     *:(仅表示次数,不同于glob)匹配前面的字符任意次,包括0次。

         例如:grep “x*y” 可以匹配abxy,xay,xxxy

         贪婪模式:默认贪婪,匹配所有符合项。xxxxxxxxy全匹配

     .*:任意长度任意字符

     \?:匹配\前面的字符0次或1次。即前面的字符可有可无

     \+:匹配\前面字符至少一次

     \{n\}:匹配\前面字符n次

     \{m,n\}:匹配\前面字符m到n次

grep、正则表达式、bash基础特性(运算) 2020/1/3_第1张图片

位置锚定:

^:行首锚定:用于模式最左侧

$:行尾锚定:用于模式最右侧

^PATTERN$:模式要能匹配整行信息

^$:空行        ^[[:space:]]*$:行首尾空格大于等于0

\< 或 \b:单词词首锚定,用于单词左侧

\> 或 \b:单词词尾锚定,用于单词右侧

\:匹配整个单词

 

分组符号:\(\):将一个或者多个字符捆绑在一起,当作一个整体进行处理

\(xy\)*ab:即锚定xy为单位出现n次

 

分组括号中的模式匹配到的内容会被正则表达式引擎记录于内部的变量中,这些变量的命名方式为:\1   ,     \2   ,    \3     等等

\1:表示从左侧起,第一个左括号以及与之匹配右括号之间的模式所匹配到的字符:

   如:\(ab\+\(xy\)*\)

       \1:引用ab\+\(xy\)*

       \2:引用xy

 

后向引用:引用前面的分组括号中的模式所匹配字符,(而非模式本身)

 

练习:

显示/proc/meminfo文件中以大小s开头的行(使用两种方式)

显示/etc/passwd文件中不以bin/bash结尾的行

显示/etc/passwd文件中ID号最大的用户的用户名

如果用户root存在,显示其默认的shall程序

找出/etc/passwd 中的两位或者三位数

找出/etc/rc.d/rc.sysinit文件中,至少以一个空白字符开头且后面存在非空白字符的行

找出“netstat -tan”命令的结果中以”LISTEN”后跟数个空白字符结尾的行

添加用户bash、testbash、basher以及nologin(其shell为/sbin/nologin):而后找出/etc/passwd文件中用户名同shell名行。

 [root@centos6 ~]# grep --color=auto '^\(\<[[:alnum:]]\+\>\).*\1$' /etc/passwd

^\(\<[[:alnum:]]\+\>\).*\1$   ——数字+字母

^\(\<[[:alnum:]]\+\>\).*\1$   ——一个或一个以上的(数字+字母)

^\(\<[[:alnum:]]\+\>\).*\1$   ——单词首尾锚定

^\(\<[[:alnum:]]\+\>\).*\1$   ——分组

^\(\<[[:alnum:]]\+\>\).*\1$   ——中间跟任意字符

^\(\<[[:alnum:]]\+\>\).*\1$   ——行首锚定

^\(\<[[:alnum:]]\+\>\).*\1$   ——(后向引用)行尾匹配\<[[:alnum:]]\+\>内容

 

写一个脚本,实现如下功能:

如果用户user1存在,则显示存在。否则添加用户。并显示添加用户的ID等信息

grep、正则表达式、bash基础特性(运算) 2020/1/3_第2张图片

写脚本:

若有root登录则显示其登录,否则显示其未登录。

 

egrep:扩展正则表达式

egrep = grep -E

扩展正则表达式的元字符:

   字符匹配:.   [ ]   [^]

   次数匹配:* 匹配任意次    ?匹配0或1次    + 匹配一次或多次

             {m} 匹配m次   {m,n} 匹配m到n次   

   锚定:

   行:^ &     词: \< \b     \> \b  

  

分组:()

向后引用:\1  \2  ……

或者:a|b      C|cat:C或cat      (C|c)at:Cat或者cat

 

练习:

  1. 显示当前系统上root,centos或user1用户的默认shell和UID

  1. 找出/etc/rc.d/init.d/functions文件(centos6)中,某单词后面跟一个小括号的行

  

 

  1. 使用echo输出一个路径,使用egrep取出其基名。(路径基名basename:路径的最后一段    目录名dirname:取基名以外的前半段)

再,使用egrep 取出路径的目录名:

 

  1. 找出ifconfig命令结果中1-255之间的任意数值

 

 

  1. 找出ifconfig命令结果中的IP地址

 

fgrep

不支持正则表达式,仅仅匹配给定字符串。所以快速。

 

 

bash 的基础特性

变量类型(决定):数据的存储格式、存储空间大小、参与运算种类

 

字符型;数值型(整型、浮点型)

 

强类型:定义变量时必须指定类型、参与运算必须符合类型要求

弱类型:无须指定类型。默认均为字符型:参与运算会自动进行隐式类型转换

 bash是弱类型

 

bash中的变量的种类:

根据变量的生效范围等标准划分为:

 本地变量:生效范围为当前shell进程。对其他shell和当前shell的子进程、父进程均无效

 环境变量:生效范围为当前shell及其子进程。对其他shell无效

 局部变量:生效范围为当前shell进程中某代码片段(通常指函数上下文)

 位置变量:$1,$2……来表示,用于让脚本在脚本代码中调用通过命令行传递给他的参数

 特殊变量:$?,$0,$#,$*,$@,

 

本地变量:

变量赋值:name=”VALUE”

         可以使用引用:

             VALUE:

  1. 可以是直接字串:name=”username”
  2. 可以是变量引用:name=”$username”
  3. 命令引用:name=`COMMAND`,name=$(COMMAND)

变量引用:${name},$name

“ ”:弱引用,其中的变量会被替换为变量值

‘ ’:强引用,其中的变量不会被替换为变量值,而保持原字符串

显示已定义的所有变量:set

销毁变量:unset name

 

环境变量:

变量声明、赋值:

export name=VALUE

declare -x name=VALUE 等同先name=VALUE再加 declare -x name

变量引用:$name,$(name)

显示所有环境变量:export,env,printenv

撤销变量:unset name

bash有许多内建的环境变量:PATH,SHELL,UID,HISTSIZE,HOME,PWD,OLD,

HISTFILE,PS1

 

变量命名法则:

  1. 不能使用程序中的关键字、保留字:如 if,for
  2. 只能使用数字,字母及下划线,且不能以数字开头
  3. 尽量做到见名知义。(为避免和环境变量冲突,尽量不用全大写命名)

 

只读变量readonly name :

   declare -r name

 

位置变量:在脚本代码中通过命令行传递给脚本的参数

$1,$2……:对应调用第1,第2等参数;

$0:调用命令本身

$*:传递给脚本的所有参数:所有参数当成一个字符串

$@:传递给脚本的所有参数:每个参数一个独立字符串

$#:传递给脚本的参数的个数:

grep、正则表达式、bash基础特性(运算) 2020/1/3_第3张图片

grep、正则表达式、bash基础特性(运算) 2020/1/3_第4张图片

换岗,剔除 shift [n]

 

示例:判断路径文件行数:

 

bash的配置文件

按生效范围划分两类:

  1. 全局配置

/etc/profile

当配置文件过大,可拆分为多个配置文件/etc/profile.d/*.sh

/etc/bashrc

  1. 个人配置

~/.bash_profile

~/.bashrc

 

按功能划分,存在两类:

  1. profile类:为交互式登录的shell提供配置

      全局:/etc/profile,/etc/profile.d/*.sh

      个人:~/.bash_profile

profile功用:

  1. 用于定义环境变量
  2. 用于运行命令或脚本

  1. bashrc类:为非交互式登录的shell提供配置
  1. 定义命令别名:
  2. 定义本地变量

 

 

shell登录的类别:

  1. 交互式登录:

直接通过终端,输入账号密码登录

使用:”su - username”或者”su -l username”切换登录的用户

文件读取顺序/etc/profile —》/etc/profile.d/*.sh —》~/.bash_profile —》~/.bashrc —》/etc/bashrc

注意:同一个变量在多个配置文件中赋值,以最后读取的配置文件为准

  1. 非交互式登录

su username

图形界面下打开的终端(伪终端)

执行脚本

文件读取顺序:~/.bashrc —》/etc/bashrc —》/etc/profile.d/*.sh

 

问题:

  1. 定义对所有用户都生效的别名

定义在/etc/bashrc中

  1. 所有用户以任意形式登录都显示的提示信息

定义在/etc/profile.d/*.sh中

  1. 让管理员/所有用户的$PATH的值多出一个路径,例如多出/usr/local/apache2/bin

以上仅对当前shell有效

永久更改所有用户或者管理员$PATH: /etc/profile.d/*.sh和~/.bash_profile

 

新配置文件的生效方式:

  1. 重新启动shell进程
  2. source 配置文件 或者 . 配置文件(副作用如下:每操作一次,路径加一次)

 

 

bash中的算数运算:加+  减-  乘*  除/  取模(余数)%   次方**

帮助:help let

   实现算数运算:

  1. let var=算数运算表达式  (运算结果定义到var,再echo var)

grep、正则表达式、bash基础特性(运算) 2020/1/3_第5张图片

  1. var=$[算数运算表达式]

  1. var=$((算数表达式))
  2. var=$(expr 参数1  参数2  参数3。。。)   ——命令引用 参数间空白分割

参数1:被操作数  参数2:运算符  参数3:操作数

注意:乘法符号*在bash的命令引用中表示通配,在某些运算中需要\转义。而在var=$[算数运算表达式]和var=$((算数表达式))中则不需要转义

 

bash内建的随机数生成器:$RANDOM——可以生成1-32767之间的随机数

如下:通过对随机数取模,生成1-60之间的随机数

判断随机生成的偶数还是奇数

 

变量取出运算后再赋值原变量:

grep、正则表达式、bash基础特性(运算) 2020/1/3_第6张图片

# a=$[$a+1]等同于# let a+=1

# let a+=1增强型赋值:意为取出a的原值,加上1,再存回a

其他增强型赋值:

+=,-=,*=,/=,%=……

若加法每次都是+1,则也可使用# let a++

 

自增,自减运算:

let var+=1   同let var++

let var-=1   同 let var--

 

练习:

  1. 写一个脚本计算/etc/passwd文件中的第10个用户和第20个用户的ID之和

2、写一个脚本,传递两个文件路径作为参数给脚本,计算这两个文件中所有空白行之和

grep、正则表达式、bash基础特性(运算) 2020/1/3_第7张图片

3、脚本:统计/etc,/var,/usr目录共有多少个一级子目录和文件

grep、正则表达式、bash基础特性(运算) 2020/1/3_第8张图片

条件测试:

判断某场景、需求是否满足,需要由测试机制来实现。

专用的测试表达式需要由测试命令辅助完成测试过程

测试命令:

  1. test 表达式
  2. [ 表达式 ]   一个[ ]是一个命令
  3. [[ 表达式 ]]  两个[[ ]]是bash内置的保留字、关键字

注:表达式前后必须要有空格,否则为语法错误

grep、正则表达式、bash基础特性(运算) 2020/1/3_第9张图片

 

bash测试类型

  1. 数值测试

-gt:是否大于

-ge:是否大于等于

-eq:是否等于

-ne:是否不等于

-lt:是否小于

-le:是否小于等于

  1. 字符串测试(用于比较的字符串都应该使用“”)

==或=:等值测试

>:是否大于

<:是否小于

!=:是否不等于

=~:左侧的字符串是否能够被右侧的模式所匹配  

      注:=~表达式一般需要[[ 表达式 ]]格式

-z “字串或者变量”:测试字串是否为空,空则为真

-n “字串或者变量”: 测试字串是否不空,不空则为真

  1. 文件测试

       -a file /-e file :文件存在性测试,存在为真 否则为假

             

       -b file :存在且为块设备

              True if file exists and is a block special file.

       -c file :存在且为字符设备文件

              True if file exists and is a character special file.

       -d file  :存在且为目录文件

              True if file exists and is a directory.

       -f file  :存在且为普通文件

              True if file exists and is a regular file.

       -g file  :文件存在,且拥有SGID权限

              True if file exists and is set-group-id.

       -h file  :存在且为符号链接文件

              True if file exists and is a symbolic link.

       -k file  :存在,且拥有sticky权限

              True if file exists and its ‘‘sticky’’ bit is set.

       -p file  :存在且为命名管道文件

              True if file exists and is a named pipe (FIFO).

       -r file  :文件存在,且拥有读权限

              True if file exists and is readable.

       -s file  :文件存在且非空

              True if file exists and has a size greater than zero.

       -t fd   :fd表示文件描述符是否已经打开且与某终端相关

True if file descriptor fd is open and refers to a terminal.

       -u file  :存在,且拥有SUID权限

              True if file exists and its set-user-id bit is set.

       -w file  :文件存在,且拥有写权限

              True if file exists and is writable.

       -x file  :文件存在,且拥有执行权限

              True if file exists and is executable.

       -O file  :当前有效用户是否为文件的属主

              True if file exists and is owned by the effective user id.

       -G file  :当前有效用户是否为文件的属组

              True if file exists and is owned by the effective group id.

       -L file  :存在且为符号链接文件

              True if file exists and is a symbolic link.

       -S file  :存在且为套接字文件

              True if file exists and is a socket.

       -N file  :文件自从上一次被读取后,是否被修改过

              True if file exists and has been modified since it was last read.

 

       file1 -nt file2:文件1是否新于文件2

True if file1 is newer (according to modification date) than file2, or if file1 exists and file2 does not.

       file1 -ot file2:文件1是否旧与文件2

True if file1 is older than file2, or if file2 exists and file1 does not.

       file1 -ef file2:文件1和文件2是否指向同一设备同一inode

True if file1 and file2 refer to the same device and inode numbers.

组合测试条件:

逻辑运算: 第一种方式:

                     命令1 && 命令2

                     命令1  ||  命令2

                      ! 命令

                                如:[ -e 文件1 ] && [ -r 文件2 ]

           第二种方式:

                    表达式1  -a  表达式2

                    表达式1  -o  表达式2

                     ! 表达式

                   必须使用测试命令进行

 

bash自定义退出状态码

   exit [n] :自定义退出状态码: echo $? 查看退出码

     注意:脚本中一旦遇到exit命令,脚本会立即终止。终止退出状态取决于exit命令后面的数字。

注意:如果未给脚本指定退出状态码,整个脚本的退出状态码取决于脚本中执行的最后一条命令的状态码。

 

练习:

写一个脚本,接受一个文件路径作为参数,

如果参数小于1 ,则提示用户“至少应该给一个参数”,并立即退出。

如果参数不小于1,则显示第一个参数所指向的文件中的空白行数。

grep、正则表达式、bash基础特性(运算) 2020/1/3_第10张图片

 

你可能感兴趣的:(linux)