Linux的Shell脚本总结

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个参数
预定义变量由系统定义完成,并且赋值完成,用户直接使用即可

$#  已加载的位置变量的个数,求和
$*  所有位置变量的值
$?  程序退出后的状态值,0表示正常,其他值异常

 ${#变量}  统计变量的长度位数

  定义变量或者赋值:变量名=变量值  ( 两边不能有空格)
  使用变量中的值:$变量名 
  取消变量 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,位置2……

  注意:
     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编辑命令   如果有多个可以用 ; 分割开来
'条件{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,最后可以完成统计。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值