Linux05
Linux05_01?egrep使用和扩展正则表达式
REGEXP:REGular EXPression,其本身可能并不表示其本身的意思,而是做锚定等特殊意义的
Pattern: 由正则表达式元字符和字符组合起来用于过滤文本的过滤条件
正则表达式:
Basic REGEXP:基本
Extended REGEXP:扩展
基本正则表达式:
.:
[]:
[^]:
次数匹配:
*:
\?: 0或1次
\{m,n\}:至少m次,至多n次;
.*:
锚定:
^:
$:
\<, \b:
\>, \b:
\(\)
\1, \2, \3, ...
grep:使用基本正则表达式定义的模式来过滤文本的命令;
-i:忽略大小写
-v:显示没有匹配的
-o:只显示被模式匹配到的字符串
--color:匹配出的字符串加上颜色
-E: 使用扩展正则表达式
----------------------------------------
-A n: 用于显示匹配到了的行的after n行
-B n: 用于显示匹配到了的行的before n行
-C n: 用于显示匹配到了的行的context n行
[[email protected] ~]# grep --color -C 1 ‘^cpu‘ /proc/cpuinfo
vendor_id : GenuineIntel
cpu family : 6
model : 42
--
stepping : 7
cpu MHz : 2394.571
cache size : 3072 KB
--
fpu_exception : yes
cpuid level : 13
wp : yes
---------------------------------------------
扩展正则表达式:
字符匹配:和正则表达式一样
.
[]
[^]
次数匹配:
*:
?:不需要\
+: 匹配其前面的字符至少1次
{m,n}:不需要\
位置锚定:和正则表达式一样
^
$
\<
\>
分组:
():真正意义上分组,不需要\
\1, \2, \3, ...
或者
|: 表示or的意思
C|cat: C或cat
(C|c)at:Cat或cat
grep -E = egrep
255 :
一位:9 [0-9]
二位:99 [1-9][0-9]
三位:199 1[0-9][0-9]; 249 2[0-4][0-9]; 255 2[0-5][0-5]
通过上面的可以退出:\<([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\>
4、显示所有以数字结尾且文件名中不包含空白的文件;
ls *[^[:space:]]*[0-9] ?????????
找出/boot/grub/grub.conf文件中1-255之间的数字;
\<([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\>
\.
ifconfig | egrep ‘\<([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\>\.\<([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\>\.\<([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\>\.\<([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\>‘
ifconfig | egrep --color ‘(\<([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\>\.){3}\<([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\>‘
IPv4:
5类:A B C D E
A:1-127 : 00000000:0:0:0~01111111:255:255:255 一段网络
B:128-191 10000000:0:0:0~10111111:255:255:255 二段网络
C:192-223 11000000:0:0:0~11000000:255:255:255 三段网络
\<([1-9]|[1-9][0-9]|1[0-9]{2}|2[01][0-9]|22[0-3])\>(\.\<([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-4])\>){2}\.\<([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-4])\>
http://mageedu.blog.51cto.com/
grep, egrep
fgrep: 不支持正则表达式
Linux05_02?bash脚本编程之一 变量、变量类型等
grep, egrep
fgrep: 不支持正则表达式
shell编程:
编译器,解释器
编程语言:机器语言、汇编语言、高级语言
静态语言:编译型语言
强类型(变量)
事先转换成可执行格式
C、C++、JAVA、C#
动态语言:解释型语言, on the fly
弱类型
边解释边执行
PHP、SHELL、python、perl
关系:一般动态语言的解释器是由静态语言编写的
面向过程:Shell, C
面向对象: JAVA, Python, perl, C++
变量:内存空间,命名
内存:编址的存储单元
进程:
1+100:
1+1000000
1
变量类型:事先确定数据的存储格式和长度
字符
数值
整型
浮点型: 11.23, 1.123*10^1, 0.1123*10^2
2013/10/10, 64bit
99999: 24bit,
布尔
逻辑运算:与、或、非、异或
1: 真
0: 假
与:&
1 & 0 = 0
0 & 1 = 0
0 & 0 = 0
1 & 1 = 1
或:!
非:
! 真 = 假
! 假 = 真
shell: 弱类型编程语言
强:变量在使用前,必须事先声明,甚至还需要初始化;
弱:变量用时声明,甚至不区分类型;
变量赋值:VAR_NAME=VALUE
bash变量类型:
环境变量
本地变量(局部变量)
位置变量:\1,\2..
特殊变量
本地变量:
set VARNAME=VALUE: 作用域为整个bash进程;
---------------------------------
[[email protected] ~]# NAME=lvyongwen (没有写类型是因为shell是弱类型的)
[[email protected] ~]# echo $NAME (可以打印出)
lvyongwen
[[email protected] ~]# bash (子shell在shell中再开启一个shell进程)
[[email protected] ~]# echo $NAME (打印不出,是因为本地变量作用范围是整个shell进程,子shell得不到)
[[email protected] ~]# exit
exit
[[email protected] ~]# echo $NAME
lvyongwen
[[email protected] ~]#
引用变量:${VARNAME} {}假如不会引起歧义的可以省略
[[email protected] ~]# NAME=lvyongwen
[[email protected] ~]# echo "My name is ${NAME}"
My name is lvyongwen
[[email protected] ~]# echo "My name is $NAME"
My name is lvyongwen
[[email protected] ~]# echo "My name is $NAMEq"
My name is
[[email protected] ~]# echo "My name is ${NAME}q"
My name is lvyongwenq
[[email protected] ~]# echo ‘My name is ${NAME}q‘
My name is ${NAME}q 没有打印出名字是因为‘‘为强引用类型,不能变量替换而""是弱类型所以可以
[[email protected] ~]#
------------------------------------
局部变量:
local VARNAME=VALUE:作用域为当前代码段;
环境变量:作用域为当前shell进程及其子进程;
定义变量1:
export VARNAME=VALUE
定义变量2:
VARNAME=VALUE
export VARNAME
“导出”
位置变量:
$1, $2, ...
特殊变量:
$?: 上一个命令的执行状态返回值;
程序执行,可能有两类返回值:
程序执行结果
程序状态返回代码(0-255)
0: 正确执行
1-255:错误执行,1,2,127系统预留;
[[email protected] ~]# ls
anaconda-ks.cfg DOS install.log test vms
C exit install.log.syslog test_dir
Desktop grant Solaris Unix
[[email protected] ~]# echo $?
0
[[email protected] ~]# lll
bash: lll: command not found
[[email protected] ~]# echo $?
127
[[email protected] ~]# ls /ss
ls: /ss: No such file or directory
[[email protected] ~]# echo $?
2
-------------------------------------
输出重定向:
>
>>
2>
2>>
&>
/dev/null: 软件设备, bit bucket(桶),数据黑洞
[[email protected] ~]# ls &> /dev/null -->所输出的结果将被吃掉
[[email protected] ~]# echo $?
0
------------------------------------------
撤消变量:
unset VARNAME
查看当shell中变量:本地和环境变量
set
查看当前shell中的环境变量:
printenv
env
export
变量存入到内存中是字符串
[[email protected] ~]# A=2
[[email protected] ~]# B=3
[[email protected] ~]# C=$A+$B
[[email protected] ~]# echo $C
2+3 <<---这里可以说明上述点
脚本:命令的堆砌,按实际需要,结合命令流程控制机制实现的源程序
-------------------------
Linux内核只识别:ELF文件类型:Executable link file
[[email protected] ~]# file /bin/ls
/bin/ls: ELF 64-bit LSB executable, AMD x86-64...
[[email protected] ~]# file ./test
./test: ASCII text
对于纯文本需要下面shebang告诉Linux内核启动解释器来解释
shebang: 魔数
#!/bin/bash
# 注释行,不执行
----
[[email protected] ~]# cat adduser.sh
#!/bin/bash <--表示需要Linux调用Linux内核解释器才能执行
adduser user1
echo "user1" | passwd --stdin user1 &> /dev/null
echo "Add user1 successfully."
[[email protected]alhost ~]# bash adduser.sh <--作为参数而执行,
Add user1 successfully.
[[email protected] ~]# tail -1 /etc/passwd
user1:x:5001:5001::/home/user1:/bin/bash
[[email protected] ~]# nano adduser.sh
[[email protected] ~]# adduser.sh <--由于没有在PATH环境变量中配置
bash: adduser.sh: command not found
[[email protected] ~]# ./adduser.sh <--没有赋值可执行权限
bash: ./adduser.sh: Permission denied
[[email protected] ~]# ls -l
total 72
-rw-r--r-- 1 root root 107 Feb 1 22:45 adduser.sh//虽然显示绿色是因为.sh默认会这样显示
[[email protected] ~]# chmod +x adduser.sh
[[email protected] ~]# ./adduser.sh
Add user1 successfully.
[[email protected] ~]#
------------------------
脚本在执行时会启动一个子shell进程;
命令行中启动的脚本会继承当前shell环境变量;
系统自动执行的脚本(非命令行启动)就需要自我定义需要各环境变量;
练习:写一个脚本,完成以下任务
1、添加5个用户, user1,..., user5
2、每个用户的密码同用户名,而且要求,添加密码完成后不显示passwd命令的执行结果信息;
3、每个用户添加完成后,都要显示用户某某已经成功添加;
useradd user1
echo "user1" | passwd --stdin user1 &> /dev/null
echo "Add user1 successfully."
练习:写一个脚本,完成以下任务
1、使用一个变量保存一个用户名;
2、删除此变量中的用户,且一并删除其家目录;
3、显示“用户删除完成”类的信息;
[[email protected] ~]# clear
[[email protected] ~]# cat userdel.sh
#!/bin/bash
USERNAME=user02
userdel -r $USERNAME --> -r表示目录邮件一并删除
echo "delete user successfully!"
Linux05_03?bash脚本编程之一条件判断
条件判断:
如果用户不存在
添加用户,给密码并显示添加成功;
否则
显示如果已经没在,没有添加;
bash中如何实现条件判断?
条件测试类型:
整数测试
字符测试
文件测试
条件测试的表达式:
[ expression ]
[[ expression ]]
test expression
整数比较:
-eq: 测试两个整数是否相等;比如 $A -eq $B
-ne: 测试两个整数是否不等;不等,为真;相等,为假;
-gt: 测试一个数是否大于另一个数;大于,为真;否则,为假;
-lt: 测试一个数是否小于另一个数;小于,为真;否则,为假;
-ge: 大于或等于
-le:小于或等于
命令的间逻辑关系:
逻辑与: &&
第一个条件为假时,第二条件不用再判断,最终结果已经有;
第一个条件为真时,第二条件必须得判断;
逻辑或: ||
第一个条件为真时,第二条件不用再判断,最终结果已经有;
第一个条件为假时,第二条件必须得判断;
逻辑非:!//单目
如果用户user6不存在,就添加用户user6
! id user6 && useradd user6
id user6 || useradd user6
如果/etc/inittab文件的行数大于100,就显示好大的文件;
[ `wc -l /etc/inittab | cut -d‘ ‘ -f1` -gt 100 ] && echo "Large file."
变量名称:
1、只能包含字母、数字和下划线,并且不能数字开头;
2、不应该跟系统中已有的环境变量重名;
3、最好做到见名知义;
如果用户存在,就显示用户已存在;否则,就添加此用户;
id user1 && echo "user1 exists." || useradd user1
如果用户不存在,就添加;否则,显示其已经存在;
! id user1 && useradd user1 || echo "user1 exists."
如果用户不存在,添加并且给密码;否则,显示其已经存在;
! id user1 && useradd user1 && echo "user1" | passwd --stdi× user1 || echo "user1 exists."
练习,写一个脚本,完成以下要求:
1、添加3个用户user1, user2, user3;但要先判断用户是否存在,不存在而后再添加;
! id user1 &> /dev/null && useradd user1 && echo "user1" | passwd --stdin user1 &> /dev/null || echo "user1 exists"
2、添加完成后,显示一共添加了几个用户;当然,不能包括因为事先存在而没有添加的;
3、最后显示当前系统上共有多少个用户;
一种:
COUNT=`wc -l /etc/passwd | cut -d‘ ‘ -f1`
echo "$COUNT users"
二种:
echo ‘this system users counts is `wc -l /etc/passwd | cut -d‘ ‘ -f1`‘×
echo "this system users counts is `wc -l /etc/passwd | cut -d‘ ‘ -f1`"√
---------------------------------
[[email protected] ~]# echo "$NAMES"-->说明弱引用可以引用变量替换
lvyongwen
[[email protected] ~]# echo ‘$NAMES‘-->说明强引用不可以引用变量替换
$NAMES
[[email protected] ~]# echo ‘"$NAMES"‘-->强引用不可以嵌套弱引用引用变量
"$NAMES"
[[email protected] ~]# echo "`ls ./`"
adduser.sh
......
[[email protected] ~]# echo ‘`ls ./`‘
`ls ./`
上面两个结果说明:
反向引用可以命令替换,而且弱引用可以嵌套反向引用引用命令而强引用不可以
[[email protected] ~]# echo "ls ./"-->说明弱引用不可以命令替换
ls ./
[[email protected] ~]# echo `$NAMES`
-bash: lvyongwen: command not found
由于反向引用认为引用的是命令,所以会报命令未找到,而且可以说明反向引用会引用变量
[[email protected] ~]# echo `id $NAMES`
uid=500(lvyongwen) gid=500(lvyongwen) groups=500(lvyongwen)
[[email protected] ~]#
---------------------------------
练习,写一个脚本,完成以下要求:
给定一个用户:
1、如果其UID为0,就显示此为管理员;
2、否则,就显示其为普通用户;
一种:
NAME="root"
[ `grep "^$NAME" /etc/passwd | cut -d: -f3` -eq 0 ] -->说明反向引用可以嵌套弱引用引用变量
&& echo "this user is root"
|| "this user is not root"
二种:
NAME=user1
USERID=`id -u $NAME` -->说明反向引用可以引用变量
[$USERID -eq 0] && echo "Adim" || echo "Commom user"
如果 UID为0;那么
显示为管理员
否则
显示为普通用户
NAME=user16
USERID=`id -u $NAME` -->使用命令的执行结果
if [ $USERID -eq 0 ]; then
echo "Admin"
else
echo "common user."
fi
NAME=user16
if [ `id -u $NAME` -eq 0 ]; then
echo "Admin"
else
echo "common user."
fi
if id $NAME; then -->使用命令的执行状态结果
Linux05_04?bash脚本编程之三条件判断 及其运算
练习:写一个脚本
判断当前系统上是否有用户的默认shell为bash;
如果有,就显示有多少个这类用户;否则,就显示没有这类用户;
grep "bash$" /etc/passwd &> /dev/null
RETVAL=$?
if [ $RETVAL -eq 0 ]; then
if grep "bash$" /etc/passwd &> /dev/null; then
提示:“引用”一个命令的执行结果,要使用命令引用;比如: RESAULTS=`wc -l /etc/passwd | cut -d: -f1`;
使用一个命令的执行状态结果,要直接执行此命令,一定不能引用;比如: if id user1一句中的id命令就一定不能加引号;
如果想把一个命令的执行结果赋值给某变量,要使用命令引用,比如USERID=`id -u user1`;
如果想把一个命令的执行状态结果保存下来,并作为命令执行成功与否的判断条件,则需要先执行此命令,而后引用其状态结果,如
id -u user1
RETVAL=$?
此句绝对不可以写为RETVAL=`id -u user1`;
练习:写一个脚本
判断当前系统上是否有用户的默认shell为bash;
如果有,就显示其中一个的用户名;否则,就显示没有这类用户;
练习:写一个脚本
给定一个文件,比如/etc/inittab
判断这个文件中是否有空白行;
如果有,则显示其空白行数;否则,显示没有空白行。
#!/bin/bash
A=`grep ‘^$‘ /etc/inittab | wc -l`
if [ $A -gt 0 ]; then
echo "$A"
else
echo "meiyoukongbaihang"
fi
—— by 张帅
#!/bin/bash
FILE=/etc/inittab
if [ ! -e $FILE ]; then
echo "No $FILE."
exit 8
fi
if grep "^$" $FILE &> /dev/null; then
echo "Total blank lines: `grep "^$" $FILE | wc -l`."
else
echo "No blank line."
fi
练习:写一个脚本
给定一个用户,判断其UID与GID是否一样
如果一样,就显示此用户为“good guy”;否则,就显示此用户为“bad guy”。
#!/bin/bash
USERNAME=user1
USERID=`id -u $USERNAME`
GROUPID=`id -g $USERNAME`
if [ $USERID -eq $GROUPID ]; then
echo "Good guy."
else
echo "Bad guy."
fi
进一步要求:不使用id命令获得其id号;
#!/bin/bash
#
USERNAME=user1
if ! grep "^$USERNAME\>" /etc/passwd &> /dev/null; then
echo "No such user: $USERNAME."
exit 1
fi
USERID=`grep "^$USERNAME\>" /etc/passwd | cut -d: -f3`
GROUPID=`grep "^$USERNAME\>" /etc/passwd | cut -d: -f4`
if [ $USERID -eq $GROUPID ]; then
echo "Good guy."
else
echo "Bad guy."
fi
练习:写一个脚本
给定一个用户,获取其密码警告期限;
而后判断用户密码使用期限是否已经小于警告期限;
提示:计算方法,最长使用期限减去已经使用的天数即为剩余使用期限;
如果小于,则显示“Warning”;否则,就显示“OK”。
圆整:丢弃小数点后的所有内容
#!/bin/bash
W=`grep "student" /etc/shadow | cut -d: -f6`
S=`date +%s`
T=`expr $S/86400`
L=`grep "^student" /etc/shadow | cut -d: -f5`
N=`grep "^student" /etc/shadow | cut -d: -f3`
SY=$[$L-$[$T-$N]]
if [ $SY -lt $W ]; then
echo ‘Warning‘
else
echo ‘OK‘
fi
—— by 董利东
练习:写一个脚本
判定命令历史中历史命令的总条目是否大于1000;如果大于,则显示“Some command will gone.”;否则显示“OK”。
变量中的赋值默认是以字符串的形式保存的
shell中如何进行算术运算:
A=3
B=6
1、let 算术运算表达式
let C=$A+$B
2、$[算术运算表达式]
C=$[$A+$B]
3、$((算术运算表达式))
C=$(($A+$B))
4、expr 算术运算表达式,表达式中各操作数及运算符之间要有空格,而且要使用命令引用
C=`expr $A + $B`
-----------------------------------
root:$1$DxJ53wWP$3ZpbWEjFJMgqzMMFgECOQ.:16425:0:99999:7:::
下面是对这个shadow文件每个条目的解释:
login name
登录名
encrypted password
被加密的密码
days since Jan 1, 1970 that password was last changed
最近一次修改密码的时间距离1970年1月的天数,最近一次被修改时间
days before password may be changed
想修改密码必须需要经过多少时间才可以,就是最短使用期限
days after which password must be changed
使用了多少天密码必须需要被修改的时间,就是最长使用期限
days before password is to expire that user is warned
为了提醒用户还有多少天过期了所设置的时间,密码快过期的警告时间
days after password expires that account is disabled
密码过期之后账号锁定之前的时间,账号过期到锁定时间
days since Jan 1, 1970 that account is disabled
过了多少时间该账号将会被锁定,账号锁定时间
a reserved field
保留字段
------------------------------------