shell解释器:
一般的shell解释器在运行某个进程的时候,会在当前bash下再创建一个子进程,而所有命令循环等都是在这个子进程下面做,创建的变量也不会影响用户登录的bash进程,只影响这个子进程。
但是!source不一样,他不生成子进程,他直接在用户登录的bash下进行操作,所有命令都直接是这个bash的子进程,声明的变量对用户登录的终端有效,所以一般不用。
控制用户属于的信息是否在屏幕中显示
将回显功能关闭
stty -echo
将回显功能恢复
stty echo
可以在输入密码前关闭回显,等输完密码再打开回显
read:产生交互,捕捉用户在键盘上的输入,并且赋值给一个变量
-p:'屏幕提示信息'
-s:不显示用户输入的数据
循环的列表值,可以不参与,循环执行的重复操作
造数工具: {起始值..结束值} {1..50}:产生1到50之间的数字
`seq 50`产生1到50之间的数字
ping命令
作用 :可以测试某台主机的连通性
使用-c选项可以设置ping的次数,
使用-i选项可以设置多次ping之间的间隔时间(单位秒),
使用-W选项可以设置ping不通时的超时时间(单位秒)。
cp 路径/文件名{,.bak} == cp 路径/文件名 路径/文件名.bak
修改配置前做好备份
自动对齐
column -t 文本
echo '内容' | column -t
排序:
sort [选项] 排序文本
选项:
-n表示按数字顺序升序排列
-r表示反序,如果要数组降序排列就要用-nr
-k可以指定按第几个字段来排序
变量:
环境变量 | 由系统定义完成,并且赋值完成,用户直接使用即可 | $USER 永远储存当前登陆的用户名 $PATH 提供命令的检索目录 $SHELL 当前解释器 $PWD 当前所在的位置(执行这个脚本终端所在位置,不是脚本的位置) $PS1 当前命令行行首如何显示 |
位置变量 | 在执行脚本时提供的命令行参数 | $1、$2、.. .. ${10}、${11}、.. ..用户输入的第n个参数 |
预定义变量 | 由系统定义完成,并且赋值完成,用户直接使用即可 | $# 已加载的位置变量的个数,求和 ${#变量} 统计变量的长度位数 |
定义变量或者赋值:变量名=变量值 ( 两边不能有空格)
使用变量中的值:$变量名
取消变量 unset [变量名]
局部变量只能对当前Shell有效,其他进程中都不能用,包括子进程
全局进程在当前Shell和该Shell的子环境都有效,注意分别shell是用bash还是source做解释器的
全局变量 :
export 变量名[=[变量值]] 把某个变量变成全局变量
export -n 变量名 取消变量全局属性
计算:
整数计算:day02
$[ 运算内容 ]
let 运算内容
计算小数 :
bc 交互计算 ,进入界面后可以自由输入运算式
$(echo "[变量1][计算符][变量2]" | bc)
逻辑判断
判断值存在问题 | |
[ -e 文件|| 目录 ] | 存在 ===> 正确 |
[ -d 目录 ] | 是目录并且存在 ===> 正确 |
[ -f 文件 ] | 是文件并且存在 ===> 正确 |
[ -d 变量 ] | 检查变量的值是否未设置(空值) |
[ -r 文件|| 目录 ] | 检查判断对象是否可读 |
[ -w 文件|| 目录 ] | 检查判断对象是否可写 |
[ -x 文件|| 目录 ] | 检查对象是否具有可执行权限 |
字符匹配 | |
[ $a == $b ] | 字符a和字符b相同 ===> 正确 |
[ $a != $b ] | 字符a和字符b不同 ===> 正确 |
整数大小比较 | |
[ $a -gt $b ] | a 大于 b ===> 正确 |
[ $a -ge $b ] | a 大于等于 b ===> 正确 |
[ $a -eq $b ] | a 等于 b ===> 正确 |
[ $a -ne $b ] | a 不等于 b ===> 正确 |
[ $a -lt $b ] | a 小于 b ===> 正确 |
[ $a -le $b ] | a 小于等于 b ===> 正确 |
小数大小比较 | |
$(echo "$变量1 ><= $变量2" | bc) | 对为1 错为0 |
逻辑符号 | 真 | 假 | 判断执行的逻辑 |
&&,逻辑与 | 两边都成立 | 一个不成立 | 逻辑符号前为真时继续执行指令 |
||,逻辑或 | 一个成立 | 两边都不成立 | 逻辑符号前为假时继续执行指令 |
; 然后 | 连接两个命令, 不需判断,执行完第一个就执行第二个。 |
if 语句
if 逻辑判断1 ;then
命令序列1
elif 逻辑判断2 ;then
命令序列2
else
命令序列n
fi
for 循环
for 变量名 in 值列表
do
命令序列
done
# 或者
for ((I=起始值;i<=终了值;i++))
do
命令序列
done
# 无限循环
for ((i=1;i<=$[i+1];i++))
do
命令序列
done
while循环
while 条件测试
do
命令序列
done
# 无限循环
while :
do
命令序列
done
中断
continue | 结束本次循环的一次循环,跳过下面语句的,但是仍然继续循环 |
break | 结束循环 |
exit | 结束脚本 |
case检索
case $变量 in # 变量前面必须有$
模式1) # 只能做等值匹配
命令序列1 ;; # 命令序列最后要有;;
模式2)
命令序列2 ;;
*)
默认命令序列
esac
函数
# 定义函数
函数名() {
命令序列
.. ..
}
# 调用函数
函数名 参数1 参数2
# 其中参数1在函数中用$1代表,可以吧函数当做一个脚本,基本的变量都能用
# 取消一个函数的定义
unset 函数名
echo的特殊用法
echo -e "\033[$编号m $内容 \033[0m"
1 | 加粗 | 7 | 变成反色,既背景色和字体色对调 |
3 | 斜体 | 9 | 字体中间划线 |
4 | 下划线 | ||
30 | 字黑色 | 90 | 字浅黑色 |
31 | 字红色 | 91 | 字浅红色 |
32 | 字绿色 | 92 | 字浅绿色 |
33 | 字黄色 | 93 | 字浅黄色 |
34 | 字蓝色 | 94 | 字浅蓝色 |
35 | 字紫色 | 95 | 字浅紫色 |
36 | 字天蓝色 | 96 | 字浅天蓝色 |
37 | 字白色 | 97 | 字浅白色 |
40 | 背景黑色 | 44 | 背景蓝色 |
41 | 背景红色 | 45 | 背景紫色 |
42 | 背景绿色 | 46 | 背景天蓝色 |
43 | 背景黄色 | 47 | 背景白色 |
后台执行
{
命令1
命令2
命令……
} &
# 这就可以使命令在后台执行,配合循环,可以实现多线程,大大提高效率
# fork炸弹
.(){ .|.&};.
注意:在程序后面加入 wait 可以使得等所有在后台子进程结束脚本结束
随机生成密码
#!/bin/bash
a='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
all=${#a}
num=8 # 密码长度
passwd=''
for i in `seq $num`
do
ran=$(echo ${a:$[$RANDOM%$all]:1})
passwd=$passwd$ran
done
echo $passwd
grep的用法
-q 检索但不输出,运行完可以用$?查看有没有匹配的
-m 数字 只检索多少行,后面的几行都不过滤了
-c 检索后输出检索到多少个
-v 检索后取反输出
-i 检索时不计较大小写
-E 调用egrep,只有egrp才能支持扩展正则,grep只能是基本正则
字符串的截取
${变量名:起始位置:长度} | 起始位置从0开始 | 起始位置:长度 | 所有参数不需要加入$ |
expr substr "$变量名" 起始位置 长度 | 起始位置是从1开始 | 起始位置 长度 | 所有参数前面必须有$ |
echo $变量名 | cut -b 截取位置 | 起始位置是从1开始 起始位置没有代表从开头开始 | 起始位置-终止位置 |
注意:
1. ${}起始位置是0,而其他都是1,在计算起始位置的时候要注意不一样,从第几个开始都要注意
2. ${#a}代表 长度,在从最后开始截取的时候计算起始位置,例如:变量a截取最后b个数字,其从1开始数的起始位置就是$[${#a}-$b+1]
字符串中匹配替换
${变量名/被替换的部分/替换成什么} 替换第一个符合被替换的部分
${变量名//被替换的部分/替换成什么} 替换所有符合被替换的部分
字符串中匹配删除
${变量名#*关键词} 把字符串从头开始删到第一个匹配关键字的位置
${变量名##*关键词} 把字符串从头开始删到最后一个匹配关键字的位置
${变量名%关键词*} 把字符串从最后开始删到最后一个匹配关键字的位置,因为是从后往前删除,所以最后一个匹配关键字的位置是删除中第一个遇到的,使用的时候,删除的是匹配出来的最小值
${变量名%%关键词*} 把字符串从最后开始删到第一个匹配关键字的位置,和上面理由相反,使用的时候,删除的是匹配出来的最大值
注意:
1.不管怎么匹配,都要注意有个*,它代表通配
2.#*符号*符号*符号*符号 代表从头删除到第4个匹配的符号的位置,包括第四个符号也删除了
字符串初值的处理
${变量:-初始值}
当变量存在且有值的时候返回变量值;当变量不存在或者为空值的时候,返回初始值
注意: 变量前不能加$ 而初始值可以用变量代表但是前面必须有$
特例: ${1:-初始值} 可以把初始值用作默认值,当用户有输入就用用户输入的,如果没有,就用默认值
数组
定义数组:
数组名=(值1 值2 值3 ……)
数组名[序号]=值 常常和循环连用
调用数组
${数组名[序号]} | 序号是从0开始,和C++语法一样 |
${数组名[@]}、${数组名[*]} | 输出所有数组中的数据 |
${#数组名[@]} | 输出数组元素的个数 |
${数组名[@]:起始下标:个数} | 从哪个下标的数组数据输出多少个(相当于把数组所有的数据进行字符串截取操作) |
expect
# 检查expect是否安装,并尝试安装
[ 'rpm -q expect' ] || yum install -y expect &>/dev/null
[ $? != 0 ] && echo your yum has problem && exit 250 || echo expect is ready
# expect格式
expect << EOF
spawn 命令 #//创建交互式进程
expect "期待出现的交互的提示随意位置的随意内容" { send "123456\r" } #//自动发送密码
……
expect "" { send "\r" }
EOF
正则
基本:基本所有软件都能使用,不过比较复杂,有很多的 \ 来控制转义,( ) { } | 这五个符号都要转义
符号 | 含义 | 符号 | 含义 | |
^ | 匹配行首 | $ | 匹配行尾 | |
[] | 匹配里面的任意一个字符 | [^] | 匹配里面一个没有的字符 | |
. | 匹配任意一个字符 | * | 匹配前面一个字符任意多次 | |
\{最少,最多\} | 匹配前一个字符多少次 | |||
a\{n,\} | 没有最多的值的话,代表匹配至少n个a字符,没有上线 | a\{n\} | 如果没有‘,’代表匹配n个a字符 | |
\| | 代表或者 | \( \) | 代表组合成整体 |
扩展:很方便,但只有部分支持,grep就不支持,如果要用必须使用egrep 当然grep -E命令也可以,因为这个命令代表调用egrep,grep自身是不支持的
符号 | 含义 | 等价 |
+ | 前面的字符最少匹配一次 | \{1,\} |
? | 前面的字符最多匹配一次 | \{0,1\} |
{最少,最多} | 匹配前一个字符多少次 | \{最少,最多\} |
() | 代表组合成整体 | \( \) |
| | 代表或者 | \| |
\b字符\b | 代表单词边界 | 这个grep不能代替,他是匹配的时候限制了单词的边界, 例如 \bgoole\b 就是匹配一个单词 goole ,两边要有空格不然不匹配,等价于\<字符\> |
特殊组合:
^$ 代表匹配所有空行
.* 任意字符任意长度,匹配所有
[^ ] 这里面有个空格,代表匹配所有没有空格的部分
注意:
* 只匹配前一个字符,再前面的与之无关
[] 注意 这里面空格也算一个字符,匹配的时候也会匹配!!
sed -- day5
前置命令 | sed [选项] '条件指令' 把前面的命令的输出结果进行编辑操作
sed [选项] '条件指令' 文件.. .. 对下面的文件逐行处理
选项
-n | 屏蔽默认输出,默认sed会输出读取文档的全部内容 |
-r | 让sed支持扩展正则 |
-i | 使得sed直接修改源文件,默认sed只是通过内存临时修改文件,对源文件无影响 |
注意:
一般命令会有 -n 让sed默认不读取,而没有 -i 让sed的语句暂时不生效
一般是在命令进行过测试后,再加入 -i 使得命令生效
条件
格式 | 作用 |
行号 命令 | 对指定行号的行进行操作 |
起始行号,终止行号 命令 | 对范围中的几行进行操作 |
行号1 命令 ; 行号2 命令; …… | 对多行进行操作,没有行号先后区分 |
起始行号,+附加的行数 命令 | 从起始行号开始,再加指定行数,这写范围内的所有行进行操作 |
起始行号~步长 命令 | 从起始行号开始,每隔一个步长的每个行进行操作 |
'2~2p' | 打印偶数行的内容 |
/正则表达式/命令 | 对匹配正则表达式的当进行操作,注意格式要求 |
$命令 | 对最后一行进行操作 |
指令
命令 | 用法及例子 | 解释 |
i | 条件 i 内容 | 在指定的行之前插入文本 |
a | 条件 a 内容 | 在指定的行之后追加文本 |
c | 条件 c 内容 | 把指定行的内容替换,整行都替换掉 |
p | 条件p | 打印符合条件的内容,注意如果没有-n,sed默认打印所有 |
!p | 条件!p | 不打印符合条件的内容,打印其他的所有 |
= | '$=' | 输出文件一共多少行,$代表最后一行,=代表输出行号 |
d | 条件d | 删除符合条件的内容 |
!d | 条件!d | 符合条件的不删除,其余删除 |
s | 条件 s/被替换内容/替换成什么/第几个 | 把文件中的每个符合条件的行的第几个匹配替换要求的内容进行替换,如果没有这么多个被替换内容就不替换,不写默认第一个 |
条件 s/被替换内容/替换成什么/g | 把文件中的每个符合条件的行的所有匹配替换要求的内容进行替换 | |
条件 s/被替换内容/替换成什么/第几个 p | 把文件中的每个符合条件的行的第几个匹配替换要求的内容进行替换,然后显示,如果前面有-n,那么就可以完成替换后只显示替换的部分信息 | |
条件 s#被替换内容#替换成什么# | s后面紧跟的符号就是控制替换符号,可以是任意字符,包括空格,字符,数字,但是不建议使用 | |
sed 's/^\(.\{'$n'\}\)\(.\)\(.*\)\(.\)\(.\{'$m'\}\)$/\1\4\3\2\5/' test.txt | 把第n+1的字符和倒数第m+1的字符对换 | |
r | 条件 r 文件2 | 把文件2(条件指令中的文件)中的内容添加文件1(sed命令后操作的文件)中到满足条件的行下 |
sed -n "2 r a.txt" b.txt | 把a.txt的内容添加到b.txt的第二行下 | |
w | 条件 w 文件2 | 把文件1(sed命令后操作的文件)中到满足条件的行另存到文件2中 |
sed -n "w a.txt" b.txt | 把b.txt的所有内容保存到a.txt中 | |
H | 条件 H | 把符合条件的行的内容写入复制版中 |
h | 条件 h | 把符合条件的行的内容覆盖写入复制版中 |
G | 条件 G | 把复制版中的内容追加到符合条件的行后面,注意也没有回车 |
g | 条件 g | 把复制版中的内容覆盖到符合条件的行后面,注意也没有回车 |
例子:'2H;3h;5H;8G;9g' 一行一行的执行 逻辑理解: 对于HhGg可以理解为,一个复制版里面本来就有一个回车,然后H是把内容追加写入到复制版的下一行中,h是把内容覆盖写入到复制版中,G是对于当前行追加写入复制版的内容,g是对于当前行进行覆盖写入 |
注意:
0. 在sed中的空格没有太过严格的要求,条件与命令间有没有空格都可以,不影响使用,
但是在用命令s进行替换的时候,每个空格都算是一个字符, s/被替换内容/替换成什么/ 这以部分间不能随便加空格,可以将其理解为一个整体 ,至于 第几个、是否打印,他们间有空格无所谓。
1. 如果想让输出有该行在源文件的位置,可以用 cat -n 文件 | sed [选项] 条件 命令
但是这时候如果用正则匹配,开头匹配就不能用了,因为内容有了改变,原本再文件中开头的数据前面都有了行号,他们就不是在行首了
2. 删除某一行或多行用命令 '条件d' ,如果删除某一行或多行中的某一些字段用 '条件s/目标字段//'
替换后一行的内容用'条件 c 内容' , 如果替换后一行中的某个字段用'条件s/被替换的部分/替换成什么/'
3. s后面紧跟的符号就是控制替换符号,可以是任意字符,包括空格,字符,数字,但是不建议使用
4. 在sed的s替换中替换成什么,这个部分,符号基本都没有特殊含义,除了 \ 和被选定作为控制替换符号 , 如果要向替换成 \ 就要打 \\ 如果向换成 \\ 就打 \\\ 依次类推 , 如果要替换成控制替换符号如 / 就要打 \/
例如: sed -n 's/[A−Z]/\/\\\1:"'/gp' 文件 其作用就是把全文所有的大写字母 变成 /\大写字母:" 然后打印出来
5. 一般sed中用 ' ' 限定起来如果要用变量可以把中间的条件命令分开来 '……'$变量'……' 这样就可以了
awk 选项 '条件{指令}' 文件
支持拓展正则
不写指令的时候默认是{print} ,打印符合条件的行的全部内容
变量
变量名 | 作用 |
自定义 | 自定义的一个变量,如果没有赋予初始值,默认为0 |
$数字n | 文本的第n列,但是$0代表文本当前行的全部内容 |
NR | 当前行号 |
NF | 当前行一共的列数 |
$(NF-数字n) | 当前行倒数第(n+1)列 |
数组名[下标] | 自定义数组,数组的下标可以是字符串,不一定要是数字 |
条件
命令格式 | 作用 |
'/正则表达式/{命令}' | 按照正则表达式匹配行,匹配成功后执行命令 |
'BEGIN{指令}' | 在读文件前执行一次 |
'END{指令}' | 在读完文件后执行一次 |
awk 选项 'BEGIN{指令1}条件{指令2}END{指令3}' | 执行指令1,然后一行一行读文件,如果哪行满足条件,执行指令2,文件完全读完后,执行指令3 |
'!/正则表达式/{命令}' | 按照正则表达式匹配行,匹配失败后执行命令 |
'$数字n~/正则表达式/{命令}' | 对每行的第n列进行正则匹配,匹配成功后执行命令 |
'$数字n!~/正则表达式/{命令}' | 对每行的第n列进行正则匹配,匹配失败后执行命令 |
'变量==具体值{命令}' | 变量和具体值完全相同,执行命令,具体值可以是变量,不是变量用" "标示出来 |
'变量!=具体值{命令}' | 变量和具体值不相同,执行命令,具体值可以是变量,不是变量用" "标示出来 |
'变量>=具体值{命令}' | 变量大于等于具体值,执行命令,具体值可以是变量,不是变量用" "标示出来 |
'变量<=具体值{命令}' | 变量小于等于具体值,执行命令,具体值可以是变量,不是变量用" "标示出来 |
'变量>具体值{命令}' | 变量大于具体值,执行命令,具体值可以是变量,不是变量用" "标示出来 |
'变量<具体值{命令}' | 变量小于具体值,执行命令,具体值可以是变量,不是变量用" "标示出来 |
'逻辑判断1&&逻辑判断2' | 满足判断1并且满足判断2的匹配成功 |
'逻辑判断1||逻辑判断2' | 满足判断1或者满足判断2的匹配成功 |
命令
命令格式 | 选项 & 作用 |
编辑命令 如果有多个可以用 ; 分割开来 | |
'条件{print $列数}' | 按照要求答应相应列数,默认分割符号是空格和制表符 |
-F 指定分割符号,F后面指定可以是任何符号(如果用\,需要写成\\),[ ]里面可以写多个分割符 | |
'条件{if(判断){命令}else{命令}}' | 多分支判断控制 |
注意:
1.如果awk中需要用常量需要用" "标示出来,而变量可以不用$,只要不是" "里面的都当成变量
2.在使用的时候print可以用逗号分割,打印的时候会出来空格,也可以不用,而多条命令可以用 ; 隔开,这杨可以一次执行
3.在脚本中如果有变量参与,可以用分号把原有命令分割开来 awk -F: '$1=="'$i'"{print $2}' /etc/shadow 这里$i就是脚本中定义的变量,如果不考虑变量内部格式应该是 '$1=="root"{print $2}' 如果想把root单独取出就把root前的$1=="用' ' 隔离开来,"{print $2}也用 ' ' 隔离开,中间的root就可以用变量代替,因为他追根究底是一个字符串,然后作为一个参数给awk
4.在awk中的for循环for(i in a) 循环的是a数组的下标,如果要遍历输出a数组的内容,用下面的语句for(i in a){print a[i]},而且数组的下标可以是字符串,不一定要是数字
统计次数:
公式:awk -F分割符号 '{a[$第几列]++}END{for(i in a){print i,a[i]}}' 文件
用来统计文件中以某列为标识,统计该标识出现多少行。
检查网页是否遭受DOS攻击,自动检测某个网页,被同一个IP访问超过1000次,这IP就算攻击者
awk '{a[$1" "$7]++}END{for(i in a){print i,a[i]}}' /var/log/httpd/access_log | awk '$3>1000{print $1,$2}'
逻辑解释:/var/log/httpd/access_log的第一列是ip,第七行是访问的网络地址,而用的是一个数组a,其下标是 [ip--地址] ,因为awk的的数组下标可以是随意的字符串,这样用下标来标示是ip和地址,相同的ip和地址就放在一起存储,有一个就+1,最后可以完成统计。