linux grep c sh,Linux中文本处理工具三剑客之一grep及shell脚本基础

01 正则表达式

REGEXP: Regular Expressions,由一类特殊字符及文本字符所编写的模式,其中有些字符(元字符)不表示字符字面意义,而表示控制或通配的功能,类似于增强版的通配符功能,但与通配符不同,通配符功能是用来处理文件名,而正则表达式是处理文本内容中字符。

正则表达式被很多程序和开发语言所广泛支持:vim, less,grep,sed,awk, nginx,mysql 等

正则表达式分两类:

基本正则表达式:BRE

扩展正则表达式:ERE

正则表达式引擎:

采用不同算法,检查处理正则表达式的软件模块,如:PCRE(Perl Compatible Regular Expressions)

正则表达式的元字符分类:字符匹配、匹配次数、位置锚定、分组

帮助:man 7 regex

1.1 基本正则表达式元字符

1.1.1 字符匹配

. 匹配任意单个字符,可以是一个汉字

[] 匹配指定范围内的任意单个字符,示例:[wang] [0-9] [a-z] [a-zA-Z]

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

[:alnum:] 字母和数字

[:alpha:] 代表任何英文大小写字符,亦即 A-Z, a-z

[:lower:] 小写字母,示例:[[:lower:]],相当于[a-z]

[:upper:] 大写字母

[:blank:] 空白字符(空格和制表符)

[:space:] 水平和垂直的空白字符(比[:blank:]包含的范围广)

[:cntrl:] 不可打印的控制字符(退格、删除、警铃...)

[:digit:] 十进制数字

[:xdigit:]十六进制数字

[:graph:] 可打印的非空白字符

[:print:] 可打印字符

[:punct:] 标点符号

范例:

1).

# .任意单个字符

[root@centos7 data]#echo r马哥t |grep r..t #成功匹配,因为匹配的是字符,不是字节

r马哥t

[root@centos7 data]#echo r马哥t |grep r.t

[root@centos7 data]#echo google |grep 'g..gle'

google

[root@centos7 data]#echo google |grep 'g.gle' #匹配失败,是因为.只能代表一个o

[root@centos7 data]#echo rdirt |grep r.t

[root@centos7 data]#echo rdit |grep r..t

rdit

2)[]

# 匹配[]内的任意单个字符

[root@centos7 ~]#ls /etc/ | grep 'rc[.0-6]'

rc0.d

rc1.d

rc2.d

rc3.d

rc4.d

rc5.d

rc6.d

rc.d

rc.local

[root@centos7 ~]#ls /etc/ | grep 'rc[.0-6].'

rc0.d

rc1.d

rc2.d

rc3.d

rc4.d

rc5.d

rc6.d

rc.d

rc.local

[root@centos7 data]#echo rc. |grep 'rc[.0-6]'

rc.

[root@centos7 data]#echo rc. |grep 'rc[.0-6].'

这个为什么匹配不上,是因为rc.匹配到[]后,后面还有一个.

这个.必须是任意一个字符,不能为空。

3)\

# \转义

[root@centos7 ~]#ls /etc/ | grep 'rc[.0-6]\.' ##rc后面跟.或0-6数字,再紧跟.的

rc0.d

rc1.d

rc2.d

rc3.d

rc4.d

rc5.d

rc6.d

[.0-6]表示的是.或0123456,而不是说.代表任意一个字符

echo rcx.local |grep 'rc[.0-6]' #匹配失败

##\转义后,后面只是个“.”;不代表任何其他字符。

[root@centos7 data]#echo rc. |grep 'rc[.0-6]\.'

[root@centos7 data]#echo rc.d |grep 'rc[.0-6]\.'

[root@centos7 data]#echo rc.. |grep 'rc[.0-6]\.'

rc..

[root@centos7 data]#echo rc.d |grep 'rc[.0-6]'

rc.d

[root@centos7 data]#echo rc.d |grep 'rc[.0-6].'

rc.d

1.1.2 匹配次数

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

* #匹配前面的字符任意次,可以是0次,一种贪婪模式,尽可能长的匹配

.* #任意长度的任意字符

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

\+ #匹配前面的字符至少1次,即肯定有>=1

\{n\} #匹配前面的字符n次

\{m,n\} #匹配前面的字符至少m次,至多n次(>m

\{,n\} #匹配前面的字符至多n次(<=n)

\{n,\} #匹配前面的字符至少n次(>=n)

范例:

1)*和.*

## *匹配前面的字符任意次,包括0次,贪婪模式:尽可能长的匹配

## .* 任意长度的任意字符

[root@centos7 data]#echo godgle |grep 'g*gle' #匹配的是gle或多个g后跟gle

godgle

[root@centos7 data]#echo godgle |grep 'go*gle' #匹配的是ggle或g多个o后跟gle,而go和gle中间还有字母d,所以匹配不上

[root@centos7 data]#echo gogle |grep 'go*gle'

gogle

[root@centos7 data]#echo gooooooogle |grep 'go*gle'

gooooooogle

[root@centos7 data]#echo gooorfeoooogle |grep 'go*gle'

[root@centos7 data]#echo gooorfeoooogle |grep 'go.*gle' #.*任意长度任意字符

gooorfeoooogle

[root@centos7 data]#echo ggle |grep 'g.*gle'

ggle

3)\?

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

[root@centos7 data]#echo ggle |grep 'g\?gle' ##匹配的是gle或ggle

ggle

[root@centos7 data]#echo gle |grep 'g\?gle' ##匹配的是gle

gle

[root@centos7 data]#echo gogle |grep 'g\?gle' ##匹配的是gle

gogle

[root@centos7 data]#echo gosdfgle |grep 'g\?gle' ##也是gle

gosdfgle

[root@centos7 data]# echo fogle |grep 'g\?gle'

fogle

[root@centos7 data]# echo fogle |grep 'h\?gle'

fogle

[root@centos7 data]#echo google |grep 'go\?gle' #匹配的是ggle或gogle

#匹配失败,是因为要匹配“o”0次或1次,但google有两个o

[root@centos7 data]# echo dgogle |grep 'go\?gle'

dgogle

[root@centos7 data]# echo dgfogle |grep 'go\?gle'

[root@centos7 data]# echo dgogle |grep 'gom\?gle' ##匹配的是gomgle或gogle

dgogle

[root@centos7 data]# echo dgomgle |grep 'gom\?gle'

dgomgle

[root@centos7 data]# echo dgmogle |grep 'gom\?gle'

[root@centos7 data]# echo gomggle |grep 'gom\?gle'

[root@centos7 data]# echo gomdsfgogle |grep 'gom\?gle'

gomdsfgogle

[root@centos7 data]# echo /etc/ |grep '/etc/\?'

/etc/

[root@centos7 data]# echo /etc |grep '/etc/\?'

/etc

4)\+

\+ 匹配其前面的字符至少1次,即:肯定有,>=1

[root@centos7 data]# echo goooooooooogle |grep 'go\+gle'

goooooooooogle

[root@centos7 data]# echo gogle |grep 'go\+gle'

gogle

[root@centos7 data]# echo ggle |grep 'go\+gle' #o至少匹配一次

[root@centos7 data]# echo /etc |grep "/etc/\+"

[root@centos7 data]# echo /etc/ |grep "/etc/\+"

/etc/

5)

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

\{m,n\} 匹配前面的字符至少m次,至多n次

\{,n\} 匹配前面的字符至多n次,<=n

\{n,\} 匹配前面的字符至少n次

[root@centos7 data]# echo goooooogle |grep 'go\{10\}gle'

[root@centos7 data]# echo goooooooooogle |grep "go\{10\}gle"

goooooooooogle

[root@centos7 data]# echo goooooooooogle |grep 'go\{3,6\}gle'

[root@centos7 data]# echo google |grep 'go\{3,6\}gle'

[root@centos7 data]# echo google |grep 'go\{2,6\}gle'

google

[root@centos7 data]# echo gooogle |grep 'go\{2,6\}gle'

gooogle

[root@centos7 data]# echo gooogle |grep 'go\{,6\}gle'

gooogle

[root@centos7 data]# echo gooogle |grep 'go\{2,\}gle'

gooogle

[root@centos7 data]# echo gogle |grep 'go\{2,\}gle'

[root@centos7 data]#

1.1.3 位置锚定

位置锚定可以用于定位出现的位置

^ #行首锚定,用于模式的最左侧

$ #行尾锚定,用于模式的最右侧

^PATTERN$ #用于模式匹配整行

^$ #空行

^[[:space:]]*$ #空白行

\< 或 \b #词首锚定,用于单词模式的左侧

\> 或 \b #词尾锚定,用于单词模式的右侧

\ #匹配整个单词。字母数字下划线组合的都是单词,其他任何符号都是分隔符

1、范例:^和$

[root@centos7 data]# grep root /etc/passwd

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

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

[root@centos7 data]# grep ^root /etc/passwd

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

[root@centos7 data]# grep /bin/bash$ /etc/passwd

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

dong:x:1000:1000::/home/dong:/bin/bash

wang:x:1001:1001::/home/wang:/bin/bash

mage:x:1002:1005::/home/mage:/bin/bash

[root@centos7 data]# grep ^[wang] /etc/passwd

adm:x:3:4:adm:/var/adm:/sbin/nologin

games:x:12:100:games:/usr/games:/sbin/nologin

nobody:x:65534:65534:Kernel Overflow User:/:/sbin/nologin

wang:x:1001:1001::/home/wang:/bin/bash

[root@centos7 data]# grep '^#' /etc/fstab

#

# /etc/fstab

# Created by anaconda on Sun Nov 15 18:21:16 2020

#

# Accessible filesystems, by reference, are maintained under '/dev/disk/'.

# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info.

#

# After editing this file, run 'systemctl daemon-reload' to update systemd

# units generated from this file.

#

[root@centos7 data]# grep ^'^#' /etc/fstab

[root@centos7 data]# grep ^'#' /etc/fstab

#

# /etc/fstab

# Created by anaconda on Sun Nov 15 18:21:16 2020

#

# Accessible filesystems, by reference, are maintained under '/dev/disk/'.

# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info.

#

# After editing this file, run 'systemctl daemon-reload' to update systemd

# units generated from this file.

#

[root@centos7 data]# grep ^UUID /etc/fstab ##只筛选uuid开头的行

UUID=52d045ca-17ce-4539-b44a-17d8699b1b19 / xfs defaults 0 0

UUID=7c4ebe9a-6c26-4f0c-bd98-f06ab3d84039 /boot ext4 defaults 1 2

UUID=853161e5-66ee-49cb-93ab-846f26397517 /data xfs defaults 0 0

UUID=5686d473-7838-4f08-933f-86c72ca51b8a swap swap defaults 0 0

[root@centos7 data]# grep -v '^#' /etc/fstab ##中间用空行的也会显示出来

UUID=52d045ca-17ce-4539-b44a-17d8699b1b19 / xfs defaults 0 0

UUID=7c4ebe9a-6c26-4f0c-bd98-f06ab3d84039 /boot ext4 defaults 1 2

UUID=853161e5-66ee-49cb-93ab-846f26397517 /data xfs defaults 0 0

UUID=5686d473-7838-4f08-933f-86c72ca51b8a swap swap defaults 0 0

[root@centos7 data]#

2、范例:\< \>

[root@centos7 data]# echo root |grep '\

root

[root@centos7 data]# echo root |grep "\

root

[root@centos7 data]# echo root |grep \

[root@centos7 data]# echo -root |grep '\

-root

[root@centos7 data]# echo _root |grep '\

[root@centos7 data]# echo 12root |grep '\

[root@centos7 data]# echo root454r |grep '\

root454r

#注意:字母数字下划线是正常字符,而其他字符如“-:”等都不是,所以-root就能筛选出来,而_root不能。

#下同

[root@centos7 data]# echo ro454root |grep 'root\>'

ro454root

[root@centos7 data]# echo ro454rootr |grep 'root\>'

[root@centos7 data]# echo ro454root: |grep 'root\>'

ro454root:

[root@centos7 data]# echo ro454root- |grep 'root\>'

ro454root-

[root@centos7 data]# echo ro454root_ |grep 'root\>'

[root@centos7 data]# echo ro454root23 |grep 'root\>'

[root@centos7 data]#

#解释同上

[root@centos7 data]# echo dkfrootlsf |grep '\'

[root@centos7 data]# echo 23root_ |grep '\'

[root@centos7 data]# echo _root: |grep '\'

[root@centos7 data]# echo -root: |grep '\'

-root:

[root@centos7 data]# echo -root* |grep '\'

-root*

[root@centos7 data]# echo -root# |grep '\'

-root#

[root@centos7 data]# echo -root@ |grep '\'

-root@

[root@centos7 data]# echo -root% |grep '\'

-root%

[root@centos7 data]# echo -root^ |grep '\'

-root^

[root@centos7 data]# echo -root~ |grep '\'

-root~

[root@centos7 data]# echo -root& |grep '\'

-bash: syntax error near unexpected token `|'

实例:提取出df的磁盘利用率

[root@centos7 ~]# df

Filesystem 1K-blocks Used Available Use% Mounted on

devtmpfs 486080 0 486080 0% /dev

tmpfs 497840 0 497840 0% /dev/shm

tmpfs 497840 7860 489980 2% /run

tmpfs 497840 0 497840 0% /sys/fs/cgroup

/dev/mapper/centos-root 17811456 2478484 15332972 14% /

/dev/sda1 1038336 228272 810064 22% /boot

tmpfs 99572 0 99572 0% /run/user/0

[root@centos7 ~]# df |grep -o '[0-9]\{1,3\}%'

0%

0%

2%

0%

14%

22%

0%

[root@centos7 ~]# df|grep ^'/dev/sd' |grep -o '[0-9]\{1,3\}%'

22%

1.1.4 分组其它

1.1.4.1 分组

分组:() 将多个字符捆绑在一起,当作一个整体处理,如:\(root\)+

后向引用:分组括号中的模式匹配到的内容会被正则表达式引擎记录于内部的变量中,这些变量的命名

方式为: \1, \2, \3, ...

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

示例:

\(string1\(string2\)\)

\1: string1\(string2\)

\2: string2

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

[root@centos7 data]# cat /data/fstab

#

# /etc/fstab

# Created by anaconda on Sun Nov 15 18:21:16 2020

#

# Accessible filesystems, by reference, are maintained under '/dev/disk/'.

# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info.

#

# After editing this file, run 'systemctl daemon-reload' to update systemd

# units generated from this file.

#

UUID=52d045ca-17ce-4539-b44a-17d8699b1b19 / xfs defaults 0 0

UUID=7c4ebe9a-6c26-4f0c-bd98-f06ab3d84039 /bo ext4 defaults 1 2

UUID=853161e5-66ee-49cb-93ab-846f26397517 /data xfs defaults 0 0

UUID=5686d473-7838-4f08-933f-86c72ca51b8a swap swap defaults 0 0

1)要将fstab中#去掉

在vim /data/fstab编辑如下

%s/^#\(.*\)/\1/ ##查找以#开头的行,把#后面的字符当作一个分组,然后用这个分组去替换“#+分组”,就去掉#号了

也可以简化

%s/^#// ##查找#开头的行,把#替换成空

2)要把UUID的行加上#

%s/^UUID/#UUID/

%s/^\(UUID\)/#\1/ ##这是把UUID整体当作一个分组

1.1.4.2 或者

或者:\|

示例:

a\|b #a或b

C\|cat #C或cat

\(C\|c\)at #Cat或cat

范例:排除空行和#开头的行

[root@centos7 data]# grep ^# /etc/fstab

#

# /etc/fstab

# Created by anaconda on Sat Jul 6 14:34:58 2019

#

# Accessible filesystems, by reference, are maintained under '/dev/disk'

# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info

#

[root@centos7 data]# grep -v '^#' /etc/fstab ##还有一个空行

/dev/mapper/centos-root / xfs defaults 0 0

UUID=4d6ce1ba-16ec-4d37-951c-afd012231267 /boot xfs defaults 0 0

/dev/mapper/centos-swap swap swap defaults 0 0

[root@centos7 data]# grep -v '^#' /etc/fstab |grep -v ^$

/dev/mapper/centos-root / xfs defaults 0 0

UUID=4d6ce1ba-16ec-4d37-951c-afd012231267 /boot xfs defaults 0 0

/dev/mapper/centos-swap swap swap defaults 0 0

[root@centos7 data]# grep -v '^#\|^$' /etc/fstab ##同上

[root@centos7 data]# grep -v '^\(#\|$\)' /etc/fstab ##同上

[root@centos7 data]# grep "^[^#]" /etc/fstab

/dev/mapper/centos-root / xfs defaults 0 0

UUID=4d6ce1ba-16ec-4d37-951c-afd012231267 /boot xfs defaults 0 0

/dev/mapper/centos-swap swap swap defaults 0 0

实例:

统计network文件去掉#和空行后,共有多少行

[root@centos7 data]# cat /etc/init.d/network|wc -l

264

[root@centos7 data]# grep -v '^#' /etc/init.d/network|grep -v '^$'|wc -l

199

[root@centos7 data]# grep -v '^#\|^$' /etc/init.d/network|wc -l

199

[root@centos7 data]# grep -v '^\(#\|$\)' /etc/init.d/network|wc -l

199

[root@centos7 data]# grep "^[^#]" /etc/init.d/network|wc -l

199

[root@centos7 data]# grep "^[^#$]" /etc/init.d/network|wc -l

199

^[^#$] 把#行和空行都排除,而^[^#]也可以。

^[^#]表示行首不能是#的一个字符,而空行不是字符。括号内表示非#,空行也是非#,但不是一个字符,所以包含在内。

1.1.5 基本正则表达式练习

1、显示/proc/meminfo文件中以大小s开头的行(要求:使用两种方法)

[root@centos7 data]# grep ^'\(S\|s\)' /proc/meminfo

SwapCached: 0 kB

SwapTotal: 2097148 kB

SwapFree: 2097148 kB

Shmem: 7828 kB

Slab: 44728 kB

SReclaimable: 20800 kB

SUnreclaim: 23928 kB

[root@centos7 data]# grep -e ^S -e ^s /proc/meminfo

SwapCached: 0 kB

SwapTotal: 2097148 kB

SwapFree: 2097148 kB

Shmem: 7828 kB

Slab: 44728 kB

SReclaimable: 20800 kB

SUnreclaim: 23928 kB

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

[root@centos7 data]# grep -v '/bin/bash$' /etc/passwd

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

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

adm:x:3:4:adm:/var/adm:/sbin/nologin

lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin

sync:x:5:0:sync:/sbin:/bin/sync

shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown

halt:x:7:0:halt:/sbin:/sbin/halt

mail:x:8:12:mail:/var/spool/mail:/sbin/nologin

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

games:x:12:100:games:/usr/games:/sbin/nologin

ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin

nobody:x:99:99:Nobody:/:/sbin/nologin

systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin

dbus:x:81:81:System message bus:/:/sbin/nologin

polkitd:x:999:998:User for polkitd:/:/sbin/nologin

sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin

postfix:x:89:89::/var/spool/postfix:/sbin/nologin

chrony:x:998:996::/var/lib/chrony:/sbin/nologin

3、显示用户wang默认的shell程序

[root@centos7 data]# grep ^wang /etc/passwd|cut -d: -f7

/bin/bash

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

[root@centos7 data]# grep -v '[0-9]\{4,\}' /etc/passwd|grep '[0-9]\{2,3\}'

mail:x:8:12:mail:/var/spool/mail:/sbin/nologin

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

games:x:12:100:games:/usr/games:/sbin/nologin

ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin

nobody:x:99:99:Nobody:/:/sbin/nologin

systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin

dbus:x:81:81:System message bus:/:/sbin/nologin

polkitd:x:999:998:User for polkitd:/:/sbin/nologin

sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin

postfix:x:89:89::/var/spool/postfix:/sbin/nologin

chrony:x:998:996::/var/lib/chrony:/sbin/nologin

5、显示CentOS7的/etc/grub2.cfg文件中,至少以一个空白字符开头的且后面有非空白字符的行

[root@centos7 data]# grep '^[[:blank:]]\+[[:graph:]]' /etc/grub2.cfg

...省略...

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

[root@centos7 data]# netstat -tan|grep 'LISTEN[[:blank:]].*'

tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN

tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN

tcp6 0 0 :::22 :::* LISTEN

tcp6 0 0 ::1:25 :::* LISTEN

[root@centos7 data]# netstat -tan|grep 'LISTEN[[:blank:]].*$'

[root@centos7 data]# netstat -tan|grep 'LISTEN[[:space:]]*$'

[root@centos7 data]# netstat -tan|grep '\'

7、显示CentOS7上所有UID小于1000以内的用户名和UID

[root@centos7 data]# grep -v '[0-9]\{4,\}' /etc/passwd|cut -d: -f1,3

root:0

bin:1

daemon:2

adm:3

lp:4

sync:5

shutdown:6

halt:7

mail:8

operator:11

games:12

ftp:14

nobody:99

systemd-network:192

dbus:81

polkitd:999

sshd:74

postfix:89

chrony:998

1.2 扩展正则表达式

1.2.1 字符匹配元字符

. #任意单个字符

[wang] #指定范围的字符

[^wang] #不在指定范围的字符

[:alnum:] #字母和数字

[:alpha:] #代表任何英文大小写字符,亦即 A-Z, a-z

[:lower:] #小写字母,示例:[[:lower:]],相当于[a-z]

[:upper:] #大写字母

[:blank:] #空白字符(空格和制表符)

[:space:] #水平和垂直的空白字符(比[:blank:]包含的范围广)

[:cntrl:] #不可打印的控制字符(退格、删除、警铃...)

[:digit:] #十进制数字

[:xdigit:] #十六进制数字

[:graph:] #可打印的非空白字符

[:print:] #可打印字符

[:punct:] #标点符号

1.2.2 匹配次数

* #匹配前面字符任意次,>=0

? #0或1次

+ #1次或多次,>=1

{n} #匹配n次

{m,n} #至少m,至多n次,>=m,<=n

{n,} #至少n次,>=n

{,n} #至多n次,<=n

1.2.3 位置锚定

^ #行首

$ #行尾

\

\>, \b #语尾

^pattern$

1.2.4 分组和其他

() #分组,后向引用:\1, \2, ...

| #或者

a|b #a或b

C|cat #C或cat

(C|c)at #Cat或cat

1.2.5 练习

1、显示三个用户root、mage、wang的UID和默认shell

[root@centos7 data]# grep '^\(root\|mage\|wang\)' /etc/passwd

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

wang:x:1013:1013::/home/wang:/bin/bash

mage:x:1014:1014::/home/mage:/bin/bash

mageia:x:1100:1100::/home/linux:/bin/bash ##mageia用户包含了mage字符,也能匹配上

[root@centos7 data]# grep ^'\(root\>\|mage\>\|wang\>\)' /etc/passwd ##加上\>,定位语尾

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

wang:x:1013:1013::/home/wang:/bin/bash

mage:x:1014:1014::/home/mage:/bin/bash

[root@centos7 data]# grep -E '^(root|mage|wang)\>' /etc/passwd ##加上\>,定位词尾

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

wang:x:1013:1013::/home/wang:/bin/bash

mage:x:1014:1014::/home/mage:/bin/bash

2、找出/etc/rc.d/init.d/functions文件中行首为某单词(包括下划线)后面跟一个小括号的行

[root@centos7 data]# grep -E ^'[[:alpha:]]|_' /etc/rc.d/init.d/functions |grep '()'

systemctl_redirect () { ###这行字母和()直接有个空格

checkpid() {

__kill_pids_term_kill_checkpids() {

__kill_pids_term_kill() {

__pids_var_run() {

__pids_pidof() {

daemon() {

killproc() {

pidfileofproc() {

pidofproc() {

status() {

echo_success() {

echo_failure() {

echo_passed() {

echo_warning() {

update_boot_stage() {

success() {

failure() {

passed() {

warning() {

action() {

strstr() {

is_ignored_file() {

convert2sec() { ##这行有数字

is_true() {

is_false() {

apply_sysctl() {

[root@centos7 data]# grep -E '^[[:alpha:]_]+\(\)' /etc/rc.d/init.d/functions

checkpid() {

__kill_pids_term_kill_checkpids() {

__kill_pids_term_kill() {

__pids_var_run() {

__pids_pidof() {

daemon() {

killproc() {

pidfileofproc() {

pidofproc() {

status() {

echo_success() {

echo_failure() {

echo_passed() {

echo_warning() {

update_boot_stage() {

success() {

failure() {

passed() {

warning() {

action() {

strstr() {

is_ignored_file() {

is_true() {

is_false() {

apply_sysctl() {

##再改进,加上包含数字和空格,就能匹配到下面的两行

[root@centos7 data]# grep -E '^[[:alnum:]_]+ ?\(\)' /etc/rc.d/init.d/functions

...以上内容,省略...

systemctl_redirect () {

convert2sec() {

3、使用egrep取出/etc/rc.d/init.d/functions中其基名

[root@centos7 data]# echo /etc/rc.d/init.d/functions |egrep -o '[^/]+/?$'

functions

[root@centos7 data]# echo /etc/rc.d/init.d/functions |egrep -o '[^/]+'|tail -1

functions

4、使用egrep取出上面路径的目录名

[root@centos7 data]# echo /etc/rc.d/init.d/functions |egrep -o '/.*/'

/etc/rc.d/init.d/

5、统计last命令中以root登录的每个主机IP地址登录次数

[root@centos7 data]# last|grep ^root|tr -s ' ' :|cut -d: -f3|sort|uniq -c

40 192.168.100.1

4 192.168.100.180

1 192.168.100.200

6、利用扩展正则表达式分别表示0-9、10-99、100-199、200-249、250-255

0-9:[0-9]

10-99:[1-9][0-9]

100-199:1[0-9][0-9]

200-249:2[0-4][0-9]

250-255:25[0-5]

7、显示ifconfig命令结果中所有IPv4地址

[root@centos7 data]# ifconfig|grep -E -o '([0-9]{1,3}\.){3}[0-9]{1,3}'

192.168.100.11

255.255.255.0

192.168.100.255

172.16.100.11

255.255.255.0

172.16.100.255

127.0.0.1

255.0.0.0

[root@centos7 data]# ifconfig|grep 'inet '|tr -s ' '|cut -d' ' -f3

192.168.100.11

172.16.100.11

127.0.0.1

8、将此字符串:welcome to magedu linux 中的每个字符去重并排序,重复次数多的排到前面

[root@centos7 data]# echo "welcome to magedu linux" |egrep -o '[[:alpha:]]'|sort|uniq -c|sort -nr

3 e

2 u

2 o

2 m

2 l

1 x

1 w

1 t

1 n

1 i

1 g

1 d

1 c

1 a

02 文本处理三剑客

grep:主要对文本的(正则表达式)行基于模式进行过滤

sed:stream editor,文本编辑工具

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

2.1 文本处理三剑客之 grep

grep:Global search REgular expression and Print out the line

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

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

格式:

grep [OPTIONS] PATTERN [FILE...]

2.1.1 常见选项

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

-m # #匹配#次后停止

-v #显示不被pattern匹配到的行

-i #忽略字符大小写

-n #显示匹配的行号

-c #统计匹配的行数

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

-q #静默模式,不输出任何信息

#例:grep -q root /etc/passwd

# echo $? #查看是否有包含root的行,0为真,非0为假

-A # #after, 后#行

-B # #before, 前#行

-C # #context, 前后各#行

-e #实现多个选项间的逻辑or关系,如:grep –e 'cat' -e 'dog' file

#或关系grep -e root -e bash /etc/passwd

#与关系grep root /etc/passwd |grep bash

-w #匹配整个单词

-E #使用ERE,相当于egrep

-F #不支持正则表达式,相当于fgrep

-f #file 根据模式文件处理

-r #递归目录,但不处理软链接

-R #递归目录,但处理软链接

2.1.2 常用选项范例

1)-o

[root@centos7 data]#grep -o 'r..t' /etc/passwd

root

root

root

root

r/ft

rypt

2)-f

##查看passwd文件中匹配f1文件的关键词的行。

[root@centos7 data]#cat f1.txt

root

bash

[root@centos7 data]#grep -f f1.txt /etc/passwd

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

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

wang:x:1000:1000::/home/wang:/bin/bash

mage:x:1001:1001::/home/mage:/bin/bash

#以上操作类似于grep -e root -e bash /etc/passwd

##取两个文件的相同行

[root@centos7 data]#cat f1.txt

a

b

1

c

[root@centos7 data]#cat f2.txt

b

e

f

c

1

2

[root@centos7 data]#grep -f f2.txt f1.txt ##从f1中选出包含在f2文件中的行

b

c

1

#相当于cat f1.txt f2.txt | sort |uniq -d #合并两个文件排序取相同行

3)-v

#基本正则表达式

[root@centos7 data]#grep -v "^#" /etc/profile | grep -v '^$'

[root@centos7 data]#grep -v "^#\|^$" /etc/profile

[root@centos7 data]#grep -v "^\(#\|$\)" /etc/profile

#扩展正则表达式

[root@centos7 data]#grep -Ev "^(#|$)" /etc/profile

[root@centos7 data]#egrep -v "^(#|$)" /etc/profile

##查询/etc/passwd包含root和bash的行

[root@centos7 data]# grep 'root\|bash' /etc/passwd

[root@centos7 data]# grep -e 'root' -e 'bash' /etc/passwd

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

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

oldboy:x:1000:1000::/home/oldboy:/bin/bash

dong:x:1001:1001::/home/dong:/bin/bash

wang:x:1013:1013::/home/wang:/bin/bash

mage:x:1014:1014::/home/mage:/bin/bash

mandriva:x:1005:2019::/home/mandriva:/bin/bash

[root@centos7 data]# grep -E 'root|bash' /etc/passwd

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

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

oldboy:x:1000:1000::/home/oldboy:/bin/bash

dong:x:1001:1001::/home/dong:/bin/bash

wang:x:1013:1013::/home/wang:/bin/bash

mage:x:1014:1014::/home/mage:/bin/bash

mandriva:x:1005:2019::/home/mandriva:/bin/bash

实例:

1)取本机磁盘利用率最高值

[root@centos7 ~]# df|grep ^'/dev/sd'|tr -s ' ' %|cut -d% -f5|sort -nr|head -1

22

2)查看并发连接最多的远程主机IP

[root@centos7 ~]# ss -nt|tail -n +2|tr -s ' ' :|cut -d: -f6|sort|uniq -c|sort -nr

4 192.168.100.1

1 192.168.100.200

1 192.168.100.180

[root@centos7 ~]# ss -nt |grep ESTAB|tr -s ' ' :|cut -d: -f6|sort|uniq -c|sort -nr

4 192.168.100.1

1 192.168.100.200

1 192.168.100.180

3)查看本机IPv4地址

[root@centos7 ~]# ifconfig|grep -E '[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}'

inet 192.168.100.11 netmask 255.255.255.0 broadcast 192.168.100.255

inet 172.16.100.11 netmask 255.255.255.0 broadcast 172.16.100.255

inet 127.0.0.1 netmask 255.0.0.0

[root@centos7 ~]#ifconfig |grep -E '([0-9]{1,3}.){3}[0-9]{1,3}'

inet 192.168.100.11 netmask 255.255.255.0 broadcast 192.168.100.255

inet 172.16.100.11 netmask 255.255.255.0 broadcast 172.16.100.255

inet 127.0.0.1 netmask 255.0.0.0

[root@centos7 ~]# ifconfig ens33|grep -Eo '([0-9]{1,3}\.){3}[0-9]{1,3}'

192.168.100.11

255.255.255.0

192.168.100.255

[root@centos7 ~]#ifconfig ens33|grep -Eo '([0-9]{1,3}\.){3}[0-9]{1,3}'|head -1

192.168.100.11

[root@centos7 ~]#cat regex.txt

([0-9]{1,3}\.){3}[0-9]{1,3}

[root@centos7 data]#ifconfig ens33|grep -oEf regex.txt

192.168.100.11

4)添加用户bash、testbash、basher、sh、nologin(其shell为/sbin/nologin),找出/etc/passwd用户

名和shell同名的行

#初始化文件

useradd bash

useradd testbash

useradd basher

useradd sh

useradd -s /sbin/nologin nologin

#以上是单独添加用户,若批量添加用户,需要使用sh脚本

#新建一个简单的uadd.sh的脚本

[root@centos7 data]# vi uadd.sh

#!/bin/bash

useradd nologin -s /sbin/nologin

for username in bash testbash basher sh

do

useradd $username

done

[root@centos7 data]# chmod +x uadd.sh ##添加可执行权限

[root@centos7 data]# sh uadd.sh ##执行脚本添加用户

[root@centos7 data]# cat /etc/passwd ##查看新建的用户

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

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

...省略...

nologin:x:2006:2006::/home/nologin:/sbin/nologin

bash:x:2007:2007::/home/bash:/bin/bash

testbash:x:2008:2008::/home/testbash:/bin/bash

basher:x:2009:2009::/home/basher:/bin/bash

sh:x:2010:2010::/home/sh:/bin/bash

##测试,找出/etc/passwd用户名和shell同名的行

[root@centos7 data]# grep '^\(.*\)\>.*\

sync:x:5:0:sync:/sbin:/bin/sync

shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown

halt:x:7:0:halt:/sbin:/sbin/halt

nologin:x:2006:2006::/home/nologin:/sbin/nologin

bash:x:2007:2007::/home/bash:/bin/bash

[root@centos7 data]# grep -E '^(.*)\>.*\

sync:x:5:0:sync:/sbin:/bin/sync

shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown

halt:x:7:0:halt:/sbin:/sbin/halt

nologin:x:2006:2006::/home/nologin:/sbin/nologin

bash:x:2007:2007::/home/bash:/bin/bash

2.1.3 练习

1、统计出/etc/passwd文件中其默认shell为非/sbin/nologin的用户个数,并将用户都显示出来

用户个数:

[root@centos7 ~]# grep -v '/sbin/nologin$' /etc/passwd|cut -d: -f1 |wc -l

17

用户:

[root@centos7 ~]# grep -v '/sbin/nologin$' /etc/passwd|cut -d: -f1

root

sync

shutdown

halt

oldboy

dong

wang

mage

mandriva

mageia

user1

user2

user3

bash

testbash

basher

sh

2、查出用户UID最大值的用户名、UID及shell类型

[root@centos7 ~]# cat /etc/passwd|sort -nrt: -k3

sh:x:2010:2010::/home/sh:/bin/bash

basher:x:2009:2009::/home/basher:/bin/bash

testbash:x:2008:2008::/home/testbash:/bin/bash

bash:x:2007:2007::/home/bash:/bin/bash

nologin:x:2006:2006::/home/nologin:/sbin/nologin

user3:x:2005:2005::/home/user3:/bin/bash

user2:x:2004:2004::/home/user2:/bin/bash

user1:x:2003:2003::/home/user1:/bin/bash

slackware:x:2002:2019::/home/slackware:/sbin/nologin

mageia:x:1100:1100::/home/linux:/bin/bash

mage:x:1014:1014::/home/mage:/bin/bash

wang:x:1013:1013::/home/wang:/bin/bash

...省略...

[root@centos7 ~]# cat /etc/passwd|sort -nrt: -k3|head -1|cut -d: -f1,3,7

sh:2010:/bin/bash

3、统计当前连接本机的每个远程主机IP的连接数,并按从大到小排序

[root@centos7 ~]# ss -nt |grep ESTAB|tr -s ' ' :|cut -d: -f6|sort|uniq -c|sort -nr

4 192.168.100.1

1 192.168.100.200

1 192.168.100.180

03 shell 脚本语言的基本用法

3.1 shell 脚本的用途

自动化常用命令

执行系统管理和故障排除

创建简单的应用程序

处理文本或文件

3.2 shell 脚本基本结构

shell脚本编程:是基于过程式、解释执行的语言

编程语言的基本结构:

各种系统命令的组合

数据存储:变量、数组

表达式:a + b

控制语句:if

shell脚本:包含一些命令或声明,并符合一定格式的文本文件

格式要求:首行shebang机制

#!/bin/bash

#!/usr/bin/python

#!/usr/bin/perl

3.3 shell脚本创建过程

第一步:使用文本编辑器来创建文本文件

第一行必须包括shell声明序列:#!

示例:添加注释,注释以#开头

#!/bin/bash

第二步:加执行权限

给予执行权限,在命令行上指定脚本的绝对或相对路径

chmod +x filename.sh

第三步:运行脚本

直接运行解释器,将脚本作为解释器程序的参数运行

. /data/filename.sh

source /data/filename.sh

sh /data/filename.sh

/bin/bash /data/filename.sh

#直接执行文件名filename.sh,前提是把当前目录.加到PATH路径中。

#如果把当前路径加到PATH变量中,就可以在当前路径执行sh脚本时,不用前面加./了。

vi /etc/profile.d/env.sh

PATH=".:$PATH"

#保存退出后,执行. /etc/profile.d/env.sh生效,即可。

#生成环境中还是要慎用。

3.4 shell 脚本注释规范

第一行一般为调用使用的语言

程序名,避免更改文件名为无法找到正确的文件

版本号

更改后的时间

作者相关信息

该程序的作用,及注意事项

最后是各版本的更新简要说明

##shell脚本注释规范

[root@centos7 ~]# vim .vimrc

1 set nu

2 set ignorecase

3 set cursorline

4 set autoindent

5 autocmd BufNewFile *.sh exec ":call SetTitle()"

6 func SetTitle()

7 if expand("%:e") == 'sh'

8 call setline(1,"#!/bin/bash")

9 call setline(2,"#")

10 call setline(3,"#***************************************")

11 call setline(4,"#Author: dong")

12 call setline(5,"#QQ: 25448779")

13 call setline(6,"#Date: ".strftime("%Y-%m-%d"))

14 call setline(7,"#FileName: ".expand("%"))

15 call setline(8,"#URL: http://www.magedu.com")

16 call setline(9,"#Description: The test script")

17 call setline(10,"#Copyright (C): ".strftime("%Y")." All rights reserved")

18 call setline(11,"#***************************************")

19 call setline(12,"")

20 endif

21 endfunc

22 autocmd BufNewFile * normal G

[root@centos7 scripts]# vim hello.sh

1 #!/bin/bash

2 #

3 #***************************************

4 #Author: dong

5 #QQ: 25448779

6 #Date: 2020-12-26

7 #FileName: hello.sh

8 #URL: http://www.magedu.com

9 #Description: The test script

10 #Copyright (C): 2020 All rights reserved

11 #***************************************

12

3.5 第一个脚本

3.5.1 第一个 Shell 脚本 hello world

[root@centos7 scripts]# vim hello.sh

1 #!/bin/bash

2 #

3 #***************************************

4 #Author: dong

5 #QQ: 25448779

6 #Date: 2020-12-26

7 #FileName: hello.sh

8 #URL: http://www.magedu.com

9 #Description: The first script

10 #Copyright (C): 2020 All rights reserved

11 #***************************************

12 #经典写法

13 echo "hello, world"

14 #流行写法

15 echo 'Hello, world!'

16

#执行方法1:没有执行权限时,使用bash .sh脚本来执行

[root@centos7 scripts]# bash hello.sh

hello, world

Hello, world!

#执行方法2

[root@centos7 scripts]# cat hello.sh |bash

hello, world

Hello, world!

#执行方法3

[root@centos7 scripts]# chmod +x hello.sh

#绝对路径

[root@centos7 ~]# /scripts/hello.sh

hello, world

Hello, world!

#相对路径

[root@centos7 ~]# cd /scripts

[root@centos7 scripts]# ./hello.sh

hello, world

Hello, world!

[root@centos7 scripts]# source hello.sh

hello, world

Hello, world!

#执行方法4,本方法可以实现执行远程主机的shell脚本

[root@web01 ~]# hostname -I

192.168.100.31

[root@web01 ~]# yum -y install nginx

[root@web01 ~]# nginx

[root@web01 ~]# cd /usr/share/nginx/html

[root@web01 html]# vim hello.sh

[root@centos7 scripts]# curl http://192.168.100.31/hello.sh|bash

% Total % Received % Xferd Average Speed Time Time Time Current

Dload Upload Total Spent Left Speed

100 42 100 42 0 0 11146 0 --:--:-- --:--:-- --:--:-- 21000

hello, world

Hello, world!

[root@centos7 scripts]# curl -s http://192.168.100.31/hello.sh|bash #-s 隐藏下载的信息

hello, world

Hello, world!

[root@centos7 scripts]# wget -qO - http://192.168.100.31/hello.sh |bash

hello, world

Hello, world!

3.5.2 备份脚本实例

[root@centos7 scripts]# vim backup.sh

1 #!/bin/bash

2 #

3 #***************************************

4 #Author: dong

5 #QQ: 25448779

6 #Date: 2020-12-26

7 #FileName: backup.sh

8 #URL: http://www.magedu.com

9 #Description: backup script

10 #Copyright (C): 2020 All rights reserved

11 #***************************************

12

13 echo -e "\033[1;31mReady to start backup...\033[0m"

14 sleep 3

15 cp -av /etc/ /data/etc`date +%F`/

16 echo -e "\E[1;32mBackup is finished! \E[0m"

[root@centos7 scripts]# bash backup.sh

Ready to start backup...

‘/etc/’ -> ‘/data/etc2020-12-26/’

‘/etc/fstab’ -> ‘/data/etc2020-12-26/fstab’

...省略...

Backup is finished!

[root@centos7 scripts]# ll /data/etc2020-12-26/ -d

drwxr-xr-x. 77 root root 8192 Dec 26 09:39 /data/etc2020-12-26/

[root@centos7 scripts]# ll /data/etc2020-12-26/|wc

188 1717 10943

[root@centos7 scripts]# ll /etc/ |wc

188 1717 10943

3.6 shell 脚本调试

bash -n:只检测脚本中的语法错误,但无法检查出命令错误,不真正执行脚本。

bash -n /path/to/some_script

bash -x:调试并执行

bash -x /path/to/some_script

范例:

1)bash -n

[root@centos7 scripts]# vim test.sh

1 #!/bin/bash

2 #

3 #***************************************

4 #Author: dong

5 #QQ: 25448779

6 #Date: 2020-12-26

7 #FileName: test.sh

8 #URL: http://www.magedu.com

9 #Description: The test script

10 #Copyright (C): 2020 All rights reserved

11 #***************************************

12

13 echo line1

14 hostnam

15 cat > test.txt <

16 aaa

17 bbb

18 ccc

19 EOF

20

21 echo line2

[root@centos7 scripts]# bash -n test.sh

test.sh: line 22: warning: here-document at line 15 delimited by end-of-file (wanted `EOF')

#执行时提示错误信息,通过cat -A查看隐藏字符

[root@centos7 scripts]# cat -A test.sh

echo line1$

hostnam$

cat > test.txt <

aaa$

bbb$

ccc$

EOF $

$

echo line2$

$

#也可以在vim中查看

[root@centos7 scripts]# vim test.sh

13 echo line1$

14 hostnam$

15 cat > test.txt <

16 aaa$

17 bbb$

18 ccc$

19 EOF $

20 $

21 echo line2$

22 $

:set list ##vim编辑器里,使用set list也可以查看隐藏字符

#提示信息为界定符的问题,查看到第19行的EOF结尾有个空格,将其删除后正常

[root@centos7 scripts]# bash -n test.sh

[root@centos7 scripts]#

2)bash -x

#但执行的时候,提示命令错误信息,-n选项检查不出来,这就需要-x选项

[root@centos7 scripts]# bash test.sh

line1

test.sh: line 14: hostnam: command not found

line2

# bash -x选项,边调试边执行

[root@centos7 scripts]# bash -x test.sh

+ echo line1

line1

+ hostnam

test.sh: line 14: hostnam: command not found #检查出命令错误信息

+ cat

+ echo line2

line2

总结:脚本错误常见的有三种

语法错误:会导致后续的命令不继续执行,可以用bash -n 检查错误,提示的出错行数不一定是准确的

命令错误:默认后续的命令还会继续执行,用bash -n 无法检查出来 ,可以使用 bash -x 进行观察

逻辑错误:只能使用 bash -x 进行观察

3.7 变量

3.7.1 变量

变量表示命名的内存空间,将数据放在内存空间中,通过变量名引用来获取数据。

3.7.2 变量类型

1、变量类型:

内置变量:如:PS1,PATH,UID,HOSTNAME,$$,BASHPID,PPID,$?,HISTSIZE

用户自定义变量:

不同的变量存放的数据不同,决定了:

数据存储方式

参与的运算(数学运算、字符相连或取字符串的一部分)

表示的数据范围

2、变量数据类型:

字符

数值:整型、浮点型,bash 不支持浮点数

3.7.3 编程语言分类

1、静态和动态语言

静态编译语言:使用变量前,先声明变量类型,之后类型不能改变,在编译时检查,如:java,c

动态编译语言:不用事先声明,可随时改变类型,如:bash,Python

2、强类型和弱类型语言

强类型语言:不同类型数据操作,必须经过强制转换成同一类型才能运算,如java , c# ,python

如:参考以下 python 代码

print('magedu'+ 10) 提示出错,不会自动转换类型

print('magedu'+str(10)) 结果为magedu10,需要显示转换类型

弱类型语言:语言的运行时会隐式做数据类型转换。无须指定类型,默认均为字符型;参与运算会

自动进行隐式类型转换;变量无须事先定义可直接调用

如:bash ,php,javascript

3.7.4 Shell中变量命名法则

不能使程序中的保留字(关键字):如:if, for

只能使用数字、字母及下划线,且不能以数字开头,注意:不支持短横线 “ - ”,和主机名相反

见名知义,用英文单词命名,并体现出实际作用,不要用简写,如:ATM

统一命名规则:驼峰命名法, studentname,大驼峰StudentName 小驼峰studentName

变量名大写:STUDENT_NAME

局部变量小写

函数名小写

3.7.5 变量定义和引用

变量的生效范围等标准来划分变量类型。

普通变量:生效范围为当前shell进程;对当前shell之外的其它shell进程,包括当前shell的子shell进程均无效

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

本地变量:生效范围为当前shell进程中某代码片断,通常指函数

变量赋值:

name='value'

#value 可以是以下多种形式

直接字串:name='root'

变量引用:name="$USER"

命令引用:name=`COMMAND` 或者 name=$(COMMAND)

#赋值前后不能有空格,都会报错

TITLE ='cto'

TITLE= 'cto'

TITLE = 'cto'

[root@centos7 scripts]# TITLE ='cto'

-bash: TITLE: command not found

[root@centos7 scripts]# TITLE= 'cto'

-bash: cto: command not found

[root@centos7 scripts]# TITLE = 'cto'

-bash: TITLE: command not found

[root@centos7 scripts]# TITLE='cto'

[root@centos7 scripts]# echo $TITLE

cto

==注意:变量赋值是临时生效,当退出终端后,变量会自动删除,无法持久保存,脚本中的变量会随着脚本结束,也会自动删除。==

变量引用:

$name

${name}

弱引用和强引用:

"$name " 弱引用,其中的变量引用会被替换为变量值

'$name ' 强引用,其中的变量引用不会被替换为变量值,而保持原字符串

范例:变量的各种赋值方式和引用

[root@centos7 scripts]# TITLE='cto'

[root@centos7 scripts]# echo $TITLE

cto

[root@centos7 scripts]# echo I am $TITLE

I am cto

[root@centos7 scripts]# echo "I am $TITLE" #弱引用

I am cto

[root@centos7 scripts]# echo 'I am $TITLE' #强引用

I am $TITLE

[root@centos7 scripts]# NAME=$USER #内建的环境变量USER,默认显示当前用户root

[root@centos7 scripts]# echo $NAME

root

[root@centos7 scripts]# USER=`hostname` #修改USER的变量为`hostname`

[root@centos7 scripts]# echo $USER

centos7

[root@centos7 scripts]# echo ${USER}

centos7

[root@centos7 scripts]# FILE=`ls /run`

[root@centos7 scripts]# echo $FILE

auditd.pid chrony console crond.pid cron.reboot cryptsetup dbus dmeventd-client dmeventd-server faillock initramfs lock log lvm lvmetad.pid mount netreport NetworkManager plymouth sepermit setrans sshd.pid sudo syslogd.pid systemd tmpfiles.d tuned udev user utmp vmware

[root@centos7 scripts]# FILE=/etc/

[root@centos7 scripts]# echo $FILE

/etc/

[root@centos7 scripts]# FILE=/etc/*

[root@centos7 scripts]# echo $FILE

/etc/adjtime /etc/aliases /etc/aliases.db /etc/alternatives /etc/anacrontab /etc/asound.conf /etc/audisp /etc/audit /etc/bash_completion.d /etc/bashrc /etc/binfmt.d /etc/centos-release ...省略...

[root@centos7 scripts]# seq 10

1

2

3

4

5

6

7

8

9

10

[root@centos7 scripts]# NUM=`seq 10`

[root@centos7 scripts]# echo $NUM

1 2 3 4 5 6 7 8 9 10

[root@centos7 scripts]# echo "$NUM"

1

2

3

4

5

6

7

8

9

10

[root@centos7 scripts]# NAMES="wang

> zhang

> zhao

> li"

[root@centos7 scripts]# echo $NAMES

wang zhang zhao li

[root@centos7 scripts]# echo "$NAMES"

wang

zhang

zhao

li

范例:变量引用

[root@centos7 scripts]# NAME=mage

[root@centos7 scripts]# AGE=20

[root@centos7 scripts]# echo $NAME $AGE

mage 20

[root@centos7 scripts]# echo $NAME$AGE

mage20

[root@centos7 scripts]# echo $NAME-$AGE

mage-20

[root@centos7 scripts]# echo $NAME:$AGE

mage:20

[root@centos7 scripts]# echo $NAME_$AGE

20

[root@centos7 scripts]# echo ${NAME}_$AGE

mage_20

范例:变量的间接赋值和引用

[root@centos7 scripts]# TITLE=cto

[root@centos7 scripts]# NAME=wang

[root@centos7 scripts]# TITLE=$NAME

[root@centos7 scripts]# echo $NAME

wang

[root@centos7 scripts]# echo $TITLE

wang

[root@centos7 scripts]# NAME=mage ##NAME赋新值

[root@centos7 scripts]# echo $NAME

mage

[root@centos7 scripts]# echo $TITLE ##而TITLE还是原来的赋值

wang

[root@centos7 scripts]# TITLE=$NAME

[root@centos7 scripts]# echo $TITLE ##再次给TITLE赋值,也变成新的值了

mage

范例:变量追加值

[root@centos7 scripts]# TITLE=CTO

[root@centos7 scripts]# TITLE+=:wang

[root@centos7 scripts]# echo $TITLE

CTO:wang

范例:利用变量实现动态命令

[root@centos7 scripts]# CMD=hostname

[root@centos7 scripts]# $CMD ##相当于执行hostname命令

centos7

[root@centos7 scripts]# echo $CMD

hostname

显示已定义的所有变量:

set

范例:

[root@centos7 scripts]# set ##当前系统下设置的所有变量(含临时变量)

AGE=20

BASH=/bin/bash

BASHOPTS=checkwinsize:cmdhist:expand_aliases:extquote:force_fignore:histappend:hostcomplete:interactive_comments:login_shell:progcomp:promptvars:sourcepath

CMD=hostname

FILE='/etc/*'

GROUPS=()

HISTCONTROL=ignoredups

HISTFILE=/root/.bash_history

HISTFILESIZE=1000

HISTSIZE=1000

HOME=/root

HOSTNAME=centos7

HOSTTYPE=x86_64

LS_COLORS='rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=01;05;37;'

MAIL=/var/spool/mail/root

NAME=mage

NAMES=$'wang\nli\nzao\nzhang'

NUM=$'1\n2\n3\n4\n5\n6\n7\n8\n9\n10'

OLDPWD=/root

PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin

PPID=1230

TITLE=CTO:wang

UID=0

USER=centos7

colors=/root/.dircolors

删除变量:

unset

范例:

[root@centos7 scripts]# NAME=mage

[root@centos7 scripts]# TITLE=ceo

[root@centos7 scripts]# echo $NAME $TITLE

mage ceo

[root@centos7 scripts]# unset $NAME ##unset+name,不加$

[root@centos7 scripts]# echo $NAME

mage

[root@centos7 scripts]# unset NAME TITLE

[root@centos7 scripts]# echo $NAME $TITLE

3.7.6 实例:显示系统信息

1、编写脚本 systeminfo.sh,显示当前主机系统信息,包括:主机名,IPv4地址,操作系统版本,内核

版本,CPU型号,内存大小,硬盘大小。

[root@centos7 scripts]# vim systeminfo.sh

1 #!/bin/bash

2 #

3 #***************************************

4 #Author: dong

5 #QQ: 25448779

6 #Date: 2020-12-26

7 #FileName: systeminfo.sh

8 #URL: http://www.magedu.com

9 #Description: The systeminfo script

10 #Copyright (C): 2020 All rights reserved

11 #***************************************

12

13 RED="\E[1;31m"

14 GREEN="\E[1;32m"

15 END="\E[0m"

16 echo -e "$GREEN----------------Host systeminfo---------------$END"

17 echo -e "HOSTNAME: $RED`hostname`$END"

18 echo -e "IPADDR: $RED`ifconfig ens33|grep -Eo '([0-9]{1,3}.){3}[0-9]{1,3}'|head -1`$END"

19 echo -e "OSVERSION: $RED`cat /etc/redhat-release`$END"

20 echo -e "KERNEL: $RED`uname -r`$END"

21 echo -e "CPU: $RED`cat /proc/cpuinfo|grep 'model name'|cut -d: -f2`$END"

22 echo -e "TOTAL MEMORY: $RED`free -h|grep 'Mem'|tr -s ' ' :|cut -d: -f2`$END"

23 echo -e "DISK: $RED`lsblk|grep '^sd'|tr -s ' ' :|cut -d: -f5`$END"

24 echo -e "$GREEN----------------------------------------------$END"

[root@centos7 scripts]# bash systeminfo.sh

----------------Host systeminfo---------------

HOSTNAME: centos7

IPADDR: 192.168.100.11

OSVERSION: CentOS Linux release 7.8.2003 (Core)

KERNEL: 3.10.0-1127.13.1.el7.x86_64

CPU: Intel(R) Core(TM) i5-4210U CPU @ 1.70GHz

TOTAL MEMORY: 972M

DISK: 20G

----------------------------------------------

2、编写脚本 backup.sh,可实现每日将/etc/目录备份到/backup/etcYYYY-mm-dd中

[root@centos7 scripts]# vim backup.sh

1 #!/bin/bash

2 #

3 #***************************************

4 #Author: dong

5 #QQ: 25448779

6 #Date: 2020-12-26

7 #FileName: backup.sh

8 #URL: http://www.magedu.com

9 #Description: backup script

10 #Copyright (C): 2020 All rights reserved

11 #***************************************

12

13 echo -e "\033[1,32mReady to start backup...\033[0m"

14 sleep 3

15 cp -av /etc/ /backup/etc`date +%F`/

16 echo -e "\E[1,31mBackup is finished! \E[0m"

[root@centos7 scripts]# bash backup.sh

Ready to start backup...

‘/etc/’ -> ‘/backup/etc2020-12-26/’

‘/etc/fstab’ -> ‘/backup/etc2020-12-26/fstab’

...省略...

Backup is finished!

[root@centos7 scripts]# ll /backup/etc2020-12-26/ -d

drwxr-xr-x. 77 root root 8192 Dec 26 09:39 /backup/etc2020-12-26/

[root@centos7 scripts]# ll /backup/etc2020-12-26/|wc

188 1717 10943

[root@centos7 scripts]# ll /etc/ |wc

188 1717 10943

3、编写脚本 disk.sh,显示当前硬盘分区中空间利用率最大的值

[root@centos7 scripts]# vim disk.sh

1 #!/bin/bash

2 #

3 #***************************************

4 #Author: dong

5 #QQ: 25448779

6 #Date: 2020-12-26

7 #FileName: disk.sh

8 #URL: http://www.magedu.com

9 #Description: Maximum disk utilization

10 #Copyright (C): 2020 All rights reserved

11 #***************************************

12

13 echo -e "Maximum disk utilization:\E[1;31m`df -h|tail -n +2|tr -s ' ' %|cut -d% -f5|sort -nr|head -1`\E[0m"

[root@centos7 scripts]# bash disk.sh

Maximum disk utilization:22

4、编写脚本 links.sh,显示正连接本主机的每个远程主机的IPv4地址和连接数,并按连接数从大到小排序。

[root@centos7 scripts]# vim link.sh

1 #!/bin/bash

2 #

3 #***************************************

4 #Author: dong

5 #QQ: 25448779

6 #Date: 2020-12-26

7 #FileName: disk.sh

8 #URL: http://www.magedu.com

9 #Description: Remote access host

10 #Copyright (C): 2020 All rights reserved

11 #***************************************

12

13 echo -e "Remote access reserved:\n\E[1;31m`ss -nt|grep ^ESTAB|tr -s ' ' :|cut -d: -f6|sort|uniq -c|sort -nr`\E[0m"

[root@centos7 scripts]# bash link.sh

Remote access reserved:

7 192.168.100.1

1 192.168.100.31

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值