0x01 正则概述
正则是用来再文件中匹配符合条件的字符串。
通配符用来匹配符合条件的文件名。
正则表达式的分类
- 基本的正则表达式(Basic Regular Expression 又叫Basic RegEx 简称BREs)
- 扩展的正则表达式(Extended Regular Expression 又叫Extended RegEx 简称EREs)
- Perl的正则表达式(Perl Regular Expression 又叫Perl RegEx 简称PREs)
命令 | 支持选项 |
---|---|
grep,aws,sed | 正则表达式 |
ls,find,cp | 通配符 |
0x02 基础正则表达式
基本正则表达式(BRE)和扩展正则表达式(ERE)
正则表达式 | 描述 | 示例 | Basic RegEx | Extended RegEx | Python RegEx | Perl regEx |
---|---|---|---|---|---|---|
\ | 转义符,将特殊字符进行转义,忽略其特殊意义 | a.b匹配a.b,但不能匹配ajb,.被转义为特殊意义 | \ | \ | \ | \ |
^ | 匹配行首,awk中,^则是匹配字符串的开始 | ^tux匹配以tux开头的行 | ^ | ^ | ^ | ^ |
$ | 匹配行尾,awk中,$则是匹配字符串的结尾 | tux$匹配以tux结尾的行 | $ | $ | $ | $ |
. | 匹配除换行符\n之外的任意单个字符,awk则中可以 | ab.匹配abc或bad,不可匹配abcd或abde,只能匹配单字符 . | . | . | . | . |
[] | 匹配包含在[字符]之中的任意一个字符 | coo[kl]可以匹配cook或cool | [] | [] | [] | [] |
[^] | 匹配[^字符]之外的任意一个字符 | 123[^45]不可以匹配1234或1235,1236、1237都可以 | [^] | [^] | [^] | [^] |
[-] | 匹配[]中指定范围内的任意一个字符,要写成递增 | [0-9]可以匹配1、2或3等其中任意一个数字 | [-] | [-] | [-] | [-] |
? | 匹配之前的项1次或者0次 | colou?r可以匹配color或者colour,不能匹配colouur | 不支持 | ? | ? | ? |
- | 匹配之前的项1次或者多次 | sa-6+匹配sa-6、sa-666,不能匹配sa- | 不支持 | + | + | +
- | 匹配之前的项0次或者多次 | co*l匹配cl、col、cool、coool等 | * | * | * | *
() | 匹配表达式,创建一个用于匹配的子串 | ma(tri)?匹配max或maxtrix | 不支持 | () | () | ()
{n} | 匹配之前的项n次,n是可以为0的正整数 | [0-9]{3}匹配任意一个三位数,可以扩展为[0-9] | 不支持 | {n} | {n} | {n}
{n,} | 之前的项至少需要匹配n次 | [0-9]{2,}匹配任意一个两位数或更多位数 | 不支持 | {n,} | {n,} | {n,}
{n,m} | 指定之前的项至少匹配n次,最多匹配m次,n<=m | [0-9]{2,5}匹配从两位数到五位数之间的任意一个数字 | 不支持 | {n,m} | {n,m} | {n,m}
| | 交替匹配 | 两边的任意一项 ab(c|d)匹配abc或abd | 不支持 | | | | | |
注意事项:
- 任何符号+*匹配所有内容例如 :
grep "a*" text.txt
因为*包含0此,所以不管有没有a都包含。 正确的内匹配所有内容应该是grep ".*" test.txt
- 匹配空白行
^$
- {}要使用转义符如
\{n\}
0x03 字符串截取和替换命令
0x031 cut列提取命令
#cut [选项] 文件名
选项:
-f 列号 : 提取第几列
-d 分隔符 : 按照指定分隔符分割列
-c 字符串范围 : 不依赖分隔符来风恶劣,。而是通过字符范围(行首为0)来进行提取。"n-"表示从第n个字符到行尾:"n-m"从第n个字符到第m个字符: "-m" 表示从第1个字符到第m个字符
例子
#cut -f 2,3 test.txt
#cut -d ":" test.txt
0x032 printf 格式化输出
printf [format] [文本1] [文本2] ..
#printf '%s' $(cat test.txt)
其与print命令的最大不同是,printf需要指定format;
format用于指定后面的每个item的输出格式;
printf语句不会自动打印换行符;\n
#printf '%s\t %s\t \n' $(cat test.txt)
常用格式替换符
代码 | 格式化意义 |
---|---|
%s | 字符串 |
%f | 浮点格式 |
%c | ASCII字符,即显示对应参数的第一个字符 |
%d,%i | 十进制整数 |
%o | 八进制值 |
%u | 不带正负号的十进制值 |
%x | 十六进制值(a-f) |
%X | 十六进制值(A-F) |
%% | 表示%本身 |
常用转义字符
代码 | 格式化意义 |
---|---|
\a | 警告字符,通常为ASCII的BEL字符 |
\b | 后退 |
\f | 换页 |
\n | 换行 |
\r | 回车 |
\t | 水平制表符 |
\v | 垂直制表符 |
\ | 表示\本身 |
不常用的转化
0x032 awk编程
awk拥有完整的编程语言
这里只写基本使用
#awk '条件1{动作} 条件2{动作}.....' 文件名
条件(Pattern):
一般使用关系表达式作为条件。这些关系表达式非常多,具体参考表12-3所示,例如:
x>10 判断变量 x是否大于10
x==y 判断变量x是否等于变量y
a ~ b 判断字符串a中是否包含b表达式的子字符串
a !~ b 判断字符串a中是否不包含b表达式的子字符串d
动作(Action):
格式化输出
流程语句控制
awk的条件
运算符 | 描述 |
---|---|
= += -= *= /= %= ^= **= | 赋值 |
?: | C条件表达式 |
&& | 逻辑与 |
~ ~! | 匹 配正则表达式和不匹配正则表达式 |
< <= > >= != == | 关 系运算符 |
空格 | 连接 |
- | 加,减
- / & | 乘,除与求余
- ! | 一元加,减和逻辑非
^ *** | 求幂
- ! | 一元加,减和逻辑非
- – | 增加或减少,作为前缀或后缀
$ | 字 段引用
in | 数组成员
- – | 增加或减少,作为前缀或后缀
awk内置变量
变 量 | 描述 |
---|---|
$n | 当前记录的第n个字段,字段间由 FS分隔。 |
$0 | 完整的输入记录。 |
ARGC | 命 令行参数的数目。 |
ARGIND | 命令行中当前文件的位置(从0开始算)。 |
ARGV | 包 含命令行参数的数组。 |
CONVFMT | 数字转换格式(默认值为%.6g) |
ENVIRON | 环 境变量关联数组。 |
ERRNO | 最后一个系统错误的描述。 |
FIELDWIDTHS | 字 段宽度列表(用空格键分隔)。 |
FILENAME | 当前文件名。 |
FNR | 同 NR,但相对于当前文件。 |
FS | 字段分隔符(默认是任何空格)。 |
IGNORECASE | 如 果为真,则进行忽略大小写的匹配。 |
NF | 当前记录中的字段数。 |
NR | 当 前记录数。 |
OFMT | 数字的输出格式(默认值是%.6g)。 |
OFS | 输 出字段分隔符(默认值是一个空格)。 |
ORS | 输出记录分隔符(默认值是一个换行符)。 |
RLENGTH | 由 match函数所匹配的字符串的长度。 |
RS | 记录分隔符(默认是一个换行符)。 |
RSTART | 由 match函数所匹配的字符串的第一个位置。 |
SUBSEP | 数组下标分隔符(默认值是\034)。 |
一般内置变量只常用$0,$n,NF,NR,FS
0x033 sed 命令
在程序中要修改数据只能用sed
#sed 选项 '动作' 文件名
选项:
-n :一般sed命令会把所有数据都输出到屏幕,如果加入此选项,会把经过sed命令处理的行输出到屏幕
-e : 允许输入数据应用多条sed命令编辑
-f 脚本名文件名 : 从sed脚本中读入sed操作。和awk命令的-f非常类似
-r : 在sed中支持扩展正则表达式
-i : 用sed的修改结果直接修改读取数据的文件,而不是由屏幕输出
动作:
a \ : 追加。在当前行后添加一行或多行,除最后一行外,每行末尾需要用"\"代表数据未完结
c \ : 行替换,用c后面的字符串替换源数据行,替换多行时,除最后一行外,每行末尾需要用"\"代表数据未完
i \ : 插入,在当期行前插入一行或多行。插入多行时,除最后一行外,每行末尾需要用"\"代表数据未完
d : 删除,删除指定的行
p : 打印,输出指定的行
s : 字串替换,用一个字符串替换另一个字符串。格式为 "行方位 s/就字符串/新字符串/g"
例如
#set '2a 1111111111111111111' test.txt a在后面i在前面
#set -e '3d ; 4d' text.txt #执行删除第三第四行数据
#set 's/new/old/g' txest.txt #全文替换
0x034 sort
sort:排序
#sort [选项] 文件名
选项:
-f : 忽略大小写
-b : 忽略每行前面的空白部分
-n : 以数值型进行排序,默认使用字符串型排序
-r : 反向排序
-u : 删除重复行.就是Uniq命令
-t : 指定分隔符,默认是分隔符是制表符
例如
# sort -r -t ':' -n -k '3,3' /etc/passwd
0x035 uniq
用来取消重复的行命令,其实和”sour -u”一样。命令格式如下:
# uniq [选项] 文件名
选项:
-i : 忽略大小写
0x036 wc
用来统计的
# wc [选项] 文件名
选项:
-l : 只统计行数
-w : 只统计单词数
-m : 只统计字符数
0x04 条件判断
0x041 按照文件类型进行判断
测试选项 | 作用 |
---|---|
-b 文件 | 判断该文件是否存在,并且是否为块设备文件 |
-c 文件 | 判断该文件是否存在,并且是否为字符设备文件 |
-d 文件 | 判断该文件是否存在,并且是否为目录文件 |
-e 文件 | 判断该文件是否存在 |
-f 文件 | 判断该文件是否存在,并且是否为普通文件 |
-L 文件 | 判断该文件是否存在,并且是否为符号链接文件 |
-p 文件 | 判断该文件是否存在,并且是否为管道文件 |
-s 文件 | 判断该文件是否存在,并且是否为空 |
-S 文件 | 判断该文件是否存在,并且是否为套接字文件 |
常用的-d,-e -f -L -s
使用方法有两种
# test -e ip.txt #方法一
# [ -e ip.txt ] #方法二 常用
例子
[ -d ip.txt ] && echo yes || echo no
0x042 按照文件权限进行判断
测试选项 | 作用 |
---|---|
-r 文件 | 判断该文件是否存在,并且是否该文件拥有读权限 |
-w 文件 | 判断该文件是否存在,并且是否该文件拥有写权限 |
-x 文件 | 判断该文件是否存在,并且是否该文件拥有执行权限 |
-u 文件 | 判断该文件是否存在,并且是否该文件拥有SUID权限 |
-g 文件 | 判断该文件是否存在,并且是否该文件拥有SGID权限 |
-k 文件 | 判断该文件是否存在,并且是否该文件拥有SBit权限 |
使用方法同上,注意这个办法不能区分所属组所属者陌生人。所以只要任意一个用户拥有权限即可。如要细分写脚本单独提取相对应的权限。
0x043 两个文件之间进行比较
测试选项 | 作用 |
---|---|
文件1 -nt 文件2 | 判断文件1d的修改时间是否比文件2的新 |
文件1 -ot 文件2 | 判断文件1d的修改时间是否比文件2的旧 |
文件1 -ef 文件2 | 判断文件1是否和文件2的Inode号一致,可以裂解为两个文件是否为同一个文件。这个判断硬链接是个很好的办法。 |
0x044 两个整数之间比较
测试选项 | 作用 |
---|---|
整数1 -eq 整数2 | 判断整数1是否和整数2相等 |
整数1 -ne 整数2 | 判断整数1是否和整数2不相等 |
整数1 -gt 整数2 | 判断整数1是否大于整数2 |
整数1 -lt 整数2 | 判断整数1是否小于整数2 |
整数1 -ge 整数2 | 判断整数1是否大于等于整数2 |
整数1 -le 整数2 | 判断整数1是否小于等于整数2 |
背诵方法 Equal 相等 greater大于 less小于
0x045 字符判断
测试选项 | 作用 |
---|---|
-z 字符串 | 判断字符串是否为空 |
-n 字符串 | 判断字符串是否为非空 |
字符串1 == 字符串2 | 判断字符串1是否和字符串2相等 |
字符串1 != 字符串2 | 判断字符串1是否不等于字符串2 |
这里==和!=可以用于判断数值是否相等因为数值的二进制码也是一样的。但是判断不了大小
0x046 条件判断
测试选项 | 作用 |
---|---|
判断1 -a 判断2 | 逻辑与,判断1和判断2都成立,则真 a=and |
判断1 -o 判断2 | 逻辑或,,判断1和判断一只有一个成立,则真 o=or |
!判断 | 逻辑非,结果取反 !=not |
例子
aa=40
[ -n "$aa" -a "$aa" -gt "30" ] && echo yes || echo no
0x05 流程控制
0x051 if条件语句
语法如下
if [条件判断式]
then
程序
fi
例子 tset.sh
#判断分区使用率是否大于80%
#!/bin/bash
aa=$(df -h | grep /dev/mapper/centos-root | awk '{print $5}' | cut -d "%" -f 1)
if [ "$aa" -ge 5 ]
then
echo "大于百分之5"
fi
0x052 双分支if条件
语法如下
if [条件判断式]
then
程序1
else
程序2
fi
例子
服务器有时候会宕机。如果我们对服务器监控不好,就会造成服务宕机,而管理员却不知道的情况,这时我们写一个脚本来监听本机的服务,如果服务器宕机就重启。例如Apache服务
#!/bin/bash
#找出端口号
port=$( nmap 192.168.205.128 | grep "tcp" | awk '$2=="open" && $3=="ssh"' )
if [ "$port" == "" ]
then
echo "httpd is down , must restart"
service httpd restart >> /dev/null
else
echo "httpd is ok"
fi
0x053 多分枝
if [条件1]
then
程序
elif [条件2]
then
程序
.....
else
当所有条件不满足时执行程序
fi
例子test3.sh
判断用户输入的是什么文件。
#!/bin/bash
#接收键盘输入,并赋予变量file
read -p "Please input a filename: " file
#判断是否为空
if [ -z $fiel ]
then
echo "Error emply input"
exit 1
#判断是否文件
elif [ ! -e $file"]
then
echo "Error input date not file"
exit 1
elif [ -f $file ]
then
echo "$file is a regulare file!"
elif [ -d $file ]
then
echo "$file is a directory!"
else
echo ""$file is an other file!"
fi
0x054 多分支case条件语句
case $变量名 in
"值1")
程序1
"值2")
程序2
;;
.....
*)
不满足条件执行程序
;;
esac
0x055 for循环
第一种写法
for 变量 in 值1 值2 值3.....
do
程序
done
第二种写法
for(( i=1;i<=100;i=i+1))
do
s=$(( $s+%i))
done
echo "1+2+。。。100 : $s"
0x056 while循环
while [ 条件判断式 ]
do
程序
条件改动
done
注意while的判断不会自增和自减。所以要条件改动
0x057 until循环
until循环和while循环相反,until是条件不满足循环
until [ 条件判断式 ]
do
程序
done
0x06 特殊流程控制语句
0x061 exit
exit [返回值]
exit常用的表示值
值 | 意义 |
---|---|
0 | 正常执行 |
1 | 报错 |
这个值可以自定义设置这样在写庞大的脚本时快速找到错误点
0x062 break和continue
break和continue普通编程一样。
0x07 加减乘除完整版
#!/bin/bash
#赋予两个变量和输入计算符号
read -t 30 -p "Please input num1: " num1
read -t 30 -p "Please input num2: " num2
read -t 30 -p "Please input operater: " ope
#判断num1,num2以及ope是否为空
if [ -n "$num1" -a -n "$num2" -a -n "$ope" ]
then
#把test1中数字替换为空。如果完后test1为空证明num1为纯数字数字
test1=$( echo $num1 | sed '/[0-9]//g' )
test2=$( echo $num2 | sed '/[0-9]//g' )
#判断test1和test2为空则输入为纯数字
if [ -z "$test1" -a -z "$test2" ]
then
case "$ope" in
"+")
value=$(( $num1 + $num2 ))
;;
"-")
value=$(( $num1 - $num2 ))
;;
"*")
value=$(( $num1 * $num2 ))
;;
"/")
value=$(( $num1 / $num2 ))
;;
*)
echo "Error, Please enter a valid symbol"
;;
esac
else
echo "Please enter a valid value"
exit 11
fi
fi
echo " $num1 $ope $num2 : $value"
0x08 判断合法IP地址
#!/bin/bash
#正则提取范围在 0-999.0-999.0-999.0-999范围的IP地址
grep "^[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}" /root/sh/ip.txt > /root/sh/ip_test1.txt
#统计test1中有几行IP地址
line=$(wc -l /root/sh/ip_tset1.txt | awk '{print $1}')
#清除数据
echo " "> /root/sh/ip_test.txt
for((i=1;i<=$line;i=i+1))
do
cat /root/sh/ip_test1.txt | awk'NR=='$i'{print}' > /root/sh/ip-test2.txt
a=$(cat /root/sh/ip_test2.txt | cut -d '.' -f1 )
b=$(cat /root/sh/ip_test2.txt | cut -d '.' -f2 )
c=$(cat /root/sh/ip_test2.txt | cut -d '.' -f3 )
d=$(cat /root/sh/ip_test2.txt | cut -d '.' -f4 )
如果IP值小于1或大于255退出
if ["$a" -lt 1 -o "$a" -gt 255]
then
continue
fi
if ["$b" -lt 0 -o "$a" -gt 255]
then
continue
fi
if ["$c" -lt 1 -o "$a" -gt 255]
then
continue
fi
if ["$d" -lt 1 -o "$a" -gt 255]
then
continue
fi
#判断玩写入文件
cat/root/sh/ip_test2.txt >> /root/sh/ip_test.txt
done
#清理临时文件
rm -rf /root/sh/ip_test1.txt
rm -rf /root/sh/ip_test2.txt
0x09 批量添加指定数量的用户
#!/bin/bash
read -p "Please input user name: " -t 30 name
read -p "Please input number of users" -t 30 num
read -p "Please input password of users" -t 30 pass
#判断三个变量都为非空
if [ !z "$name" -a ! -z "$num" -a -z "$pass"]
then
#判断Num为数字
y=$(echo $num | sed 's/[0-9]//g')
if [-z "$y"]
then
for((i=i;i<=$num;i=i+1))
do
#添加用户
/usr/sbin/useradd $name$i &>/dev/null
#设定密码
echo $pass | /usr/bin/passwd --stdin $name$i &>/dev/null
#强制用户登录后修改密码
chage -d 0 $name$i &>/dev/null
done
fi
fi
0x10 批量删除用户
#!/bin/bash
user=$( cat /etc/passwd | grep "/bin/bash" | grep -v "root" | cut -d ":" f1 )
for i in $user
do
userdel -r $i
done