shell基础

1、变量的类型
  • 字符串,a="xx"
  • 数字,i=123
  • 布尔,a=true,b=false
  • 预定义变量:echo $PWD,echo$PATH,echo$USER,echo$HOME
  • 数组变量:array=(1 2 3 4)
2、变量的使用
  • 基本使用方法

    • echo $a
    • echo $
    • echo "$a"
    • echo $?,输出上一条命名执行情况,0为正确,1为错误。
    • 注意:使用$var或${var}来访问变量,后者更为严谨。
  • 数组变量使用

    • array=( ` ls `)
    • echo ${array[2]},输出数组中的第三个元素的值
    • echo ${array},默认输出数组中的第一个元素的值
    • echo ${array[*]},默认输出数组中的全部元素的值
    • echo ${array[@]},默认输出数组中的全部元素的值
    [root@localhost ~]# echo ${array1[@]}
    123 456 789 333
    
    #从数组下标1开始,访问2个元素
    [root@localhost ~]# echo ${array1[@]:1:2}
    456 789
    
    #从数组下标1开始,访问后面的元素
    [root@localhost ~]# echo ${array1[@]:1}
    456 789 333
    
    
    • echo ${#array[*]},默认输出数组中元素的个数
    [root@localhost ~]# array1[0]=123
    [root@localhost ~]# array1[1]=456
    [root@localhost ~]# array1[2]=789
    [root@localhost ~]# echo ${array1[@]}
    123 456 789
    #打印数组下标
    [root@localhost ~]# echo ${!array1[@]}
    0 1 2
    
    
    • 关联数组
    #声明关联数组
    [root@localhost ~]# declare -A array2
    #赋值
    [root@localhost ~]# array2[name]=xyz
    [root@localhost ~]# array2[age]=18
    [root@localhost ~]# array2[home]=chengdu
    #输出数组
    [root@localhost ~]# echo ${array2[@]}
    xyz 18 chengdu
    #通过关键字访问数组值
    [root@localhost ~]# echo ${array2[age]}
    18
    [root@localhost ~]# echo ${array2[name]}
    xyz
    #访问所有索引
    [root@localhost ~]# echo ${!array2[@]}
    name age home
    #统计数组元素个数
    [root@localhost ~]# echo ${#array2[@]}
    3
    [root@localhost ~]# 
    
    
    
    • 数组统计使用

    有一个文件sex,其中f代表女性,m代表男性,统计男女个数

    aaa f
    bbb m
    ccc f
    ddd m
    aa m
    dd f
    cc f
    
    #!/usr/bin/bash
    
    #声明一个关联数组
    declare -A sex_account
    
    #读取每一行
    while read line
    do
    		#获取每一行中的第二列数
            tag=$(echo $line | awk '{print $2}')
            let sex_account[$tag]++
    
    done</root/sex
    
    
    for i in ${!sex_account[@]}
    do
            echo "索引名称是:$i;索引值个数为:${sex_account[$i]}"  
    
    done
    
    

    结果:

    [root@localhost ~]# chmod +x sex_statistics 
    [root@localhost ~]# ./sex_statistics 
    索引名称是:f;索引值个数为:4
    索引名称是:m;索引值个数为:3
    
  • 数字型变量使用

    • 整数计算
    [root@localhost ~]# a=1;echo $a;echo $((a+1))
    1
    2
    [root@localhost ~]# echo $a;echo $((a=a+1));echo $a
    1
    2
    2
    [root@localhost ~]# echo $((10+2))
    12
    [root@localhost ~]# echo $((10*2))
    20
    [root@localhost ~]# echo $((10/2))
    5
    [root@localhost ~]# echo $((3%5))
    3
    #中括号要更方便简单些
    [root@localhost ~]# echo $[1+2]
    3
    [root@localhost ~]# echo $[10-2]
    8
    [root@localhost ~]# echo $[10/2]
    5
    [root@localhost ~]# echo $[3/5]
    0
    [root@localhost ~]# echo $[3%5]
    3
    [root@localhost ~]# echo $[(1+2)*5]
    15
    
    
    • 浮点数计算
    [root@localhost ~]# awk 'BEGIN{print 1/3}'
    0.333333
    
    [root@localhost ~]# awk 'BEGIN{printf("%.2f\n",1/3)}'
    0.3
    
    • 字符串操作
    [root@localhost ~]# name="hello world"
    #取值操作
    [root@localhost ~]# echo ${name:1:3}
    ell
    #取长度操作
    [root@localhost ~]# echo ${#name}
    11
    #掐去头部的hello
    [root@localhost ~]# echo ${name#hello}
    world
    #掐去尾部的world
    [root@localhost ~]# echo ${name%world}
    hello
    #把hello替换为nihao
    [root@localhost ~]# echo ${name/hello/nihao}
    nihao world
    #匹配第一个ll并把之前的去掉
    [root@localhost ~]# echo ${name#*ll}
    o world
    #从左向右匹配第一个o并把之前的去掉
    [root@localhost ~]# echo ${name#*o}
    world
    #从左向右匹配最后一个o并把之前的去掉,*在左就是左开始匹配,*在右就从右开始匹配
    [root@localhost ~]# echo ${name##*o}
    rld
    #从右向左匹配第一个o并把尾去掉
    [root@localhost ~]# echo ${name%o*}
    hello w
    #从右向左匹配最后一个o并把尾去掉
    [root@localhost ~]# echo ${name%%o*}
    hell
    [root@localhost ~]# echo $url
    www.baidu.com
    [root@localhost ~]# echo ${url#*.}
    baidu.com
    [root@localhost ~]# echo ${url%.*}
    www.baidu
    
    
    • 布尔
    [root@localhost ~]# a=1;b=2
    [root@localhost ~]# ((a<b))
    [root@localhost ~]# echo $?
    0
    
    [root@localhost ~]# ((a>b))
    [root@localhost ~]# echo $?
    1
    #0表示正确,1表示错误
    
  • 算术判断

注意,这是整数比对,若是字符串比对需要用=或者==

  #等于,注意中括号两边都要有空格
[root@localhost ~]# [ 2 -eq 2 ];echo $?
  0
  #不等于
  [root@localhost ~]# [ 2 -ne 3 ];echo $?
  0
  #大于
  [root@localhost ~]# [ 3 -gt 2 ];echo $?
  0
  #大于等于
  [root@localhost ~]# [ 3 -ge 3 ];echo $?
  0
  #小于
  [root@localhost ~]# [ 3 -lt 4 ];echo $?
  0
  #小于等于
  [root@localhost ~]# [ 3 -le 4 ];echo $?
  0

示列:发现磁盘空间使用率大于85%时,邮件报警

#!/usr/bin/bash

Disk_Free=$(df -h | grep "/$" | awk '{ print $5 }' | awk -F "%" '{print $1}')


if [ $Disk_Free -ge 85 ];then
        echo "current disk have usage :$Disk_Free"%
fi

示列:发现内存空间使用率大于85%时,邮件报警

#!/usr/bin/bash


Mem_total=$(free -m | grep 'Mem' | awk '{print $2}')
Mem_used=$(free -m | grep 'Mem' | awk '{print $3}')
Mem_percent=$(($Mem_used*100/$Mem_total))


if [ $Mem_percent -ge 85 ];then
        echo "memery have used :"${Mem_percent}%
fi

  • 字符串比较
#等于
[root@localhost ~]# [ "aaa" = "aaa" ];echo $?
0
#不等于
[root@localhost ~]# [ "aaa" != "bbb" ];echo $?
0
#不为空时为真
[root@localhost ~]# [ -n "aaa" ];echo $?
0
#为空时为真
[root@localhost ~]# [ -z "aaa" ];echo $?
1
[root@localhost ~]# [ -z "" ];echo $?
0
#字符串中有多个a时为真
[root@localhost ~]# [[ "aaa" == a* ]];echo $?
0

#字符串比较
[root@localhost ~]# echo $a
hello

#字符串长度为0
[root@localhost ~]# [ -z $a ];echo $?
1

#字符串长度不为0
[root@localhost ~]# [ -n $a ];echo $?
0

  • 正则比对
[root@localhost ~]# num=123123
[root@localhost ~]# [[ ${num} =~ ^[0-9]+$ ]];echo $?
0
[root@localhost ~]# [[ "$num" =~ ^[0-9]+$ ]];echo $?
0

  • 逻辑判断
#与运算,也就and
[root@localhost ~]# [ 2 -ge 1 -a 3 -lt 4 ];echo $?
0
#或运算,也就是or
[root@localhost ~]# [ 2 -ge 1 -o 3 -gt 4 ];echo $?
0

#与运算,也就and
[root@localhost ~]# [[ 2 -ge 1 && 3 -gt 4 ]];echo $?
1
#或运算,也就是or
[root@localhost ~]# [[ 2 -ge 1 || 3 -gt 4 ]];echo $?
0

[root@localhost ~]# [ 2 -gt 1 ];echo $?
0
#非运算,也就是not,用感叹号表示!
[root@localhost ~]# [ ! 2 -gt 1 ];echo $?
1

注意:[[]]是[]的扩展语法,在老sh里并不支持,推荐[]
  • 内置判断
-e file如果文件存在,则为真
-d file如何文件为子目录,则为真r
-f file如何文件为一个普通文件,则为真
-r file如何文件可读,则为真
-s file如何文件长度不为0,则为真
-w file如何文件可写,则为真
-x file如何文件可执行,则为真
  • 变量赋值
[root@localhost ~]# url="www.tencent.com"
[root@localhost ~]# echo $url
www.tencent.com
[root@localhost ~]# echo ${url-www.alibaba.com}
www.tencent.com
[root@localhost ~]# unset url
[root@localhost ~]# echo $url

#相当于给url设定了默认值
[root@localhost ~]# echo ${url-www.alibaba.com}
www.alibaba.com
[root@localhost ~]#
  • 变量替代
[root@localhost ~]# url="www.xiaomi.com"
[root@localhost ~]# echo $url
www.xiaomi.com
[root@localhost ~]# echo ${url:-www.baidu.com}
www.xiaomi.com
[root@localhost ~]# unset url
[root@localhost ~]# echo ${url:-www.baidu.com}
www.baidu.com

3、文件描述符
  • 输入文件,标准输入为0
  • 输出文件,标准输出为1
  • 错误输出文件,标准错误2
4、特殊符号的使用
  • 双引号用于括起一段字符串值,支持$var形式的变量替换
[root@localhost ~]# name="this is string"
[root@localhost ~]# echo $name
this is string
  • 单引号也表示其内容是字符串值,不支持转义

  • \反斜杠某些时候表示的转义

[root@localhost ~]# echo "aaabbb"
aaabbb
[root@localhost ~]# echo -e "aaa\nbbb"
aaa
bbb
  • ((a=a+1))是整数的扩展。把里面的变量当作整数去处理。
  • $(())对变量进程操作。
[root@localhost ~]# a=1
[root@localhost ~]# b=2
[root@localhost ~]# echo $((a+b))
3
[root@localhost ~]# echo $(a+b)
-bash: a+b: 未找到命令
  • ({1..10})等价于seq 1 10,表示从1到10。
[root@localhost ~]# a=({1..10})
[root@localhost ~]# echo ${a[@]}
1 2 3 4 5 6 7 8 9 10
[root@localhost ~]# echo ${a[*]}
1 2 3 4 5 6 7 8 9 10
  • seq 1 3 10 表示生成一个1到10,步进为3。
[root@localhost ~]# a= seq 1 10
1
2
3
4
5
6
7
8
9
10
[root@localhost ~]# a= seq 1 2 10
1
3
5
7
9

  • $(ls)表示执行ls后的结果。与``类似。不过可以嵌套。
[root@localhost ~]# ls
1.sh  anaconda-ks.cfg  demo      lnmp-install.log  test1.txt      test2.txt      test.log
2.sh  cmdline          hello.sh  test              test1.txt.bak  test2.txt.bak  xyz

[root@localhost ~]# echo $(ls)
1.sh 2.sh anaconda-ks.cfg cmdline demo hello.sh lnmp-install.log test test1.txt test1.txt.bak test2.txt test2.txt.bak test.log xyz
  • `反引号。用法比较特殊,代表命名的输出。
[root@localhost ~]# echo my dir is `ls`
my dir is 1.sh 2.sh anaconda-ks.cfg cmdline demo hello.sh lnmp-install.log test test1.txt test1.txt.bak test2.txt test2.txt.bak test.log xyz
5、&&与||的用法

简单的逻辑可以使用&&和||去替代,&为真时就执行后续的代码,||为假时就执行后续的代码。

[ -e 3.sh ] && echo exist || echo not exist

表示3.sh文件存在时就输出exist,不存在时就输出not exist。可以代替简单的if...else...逻辑。

6、if逻辑结果
if [ condition ] ; then...;fi

if [ condition ] ; then...;else...;fi

if [ condition ] ; then...;elif...;fi
[root@localhost ~]# if [ -e xyz ];then echo "exist";else echo "not exist";fi
exist
[root@localhost ~]# if [ -e 111 ];then echo "exist";else echo "not exist";fi
not exist

[root@localhost ~]# [ -e xyz ] && echo "exist" || echo "not exist"
exist
[root@localhost ~]# [ -e 111 ] && echo "exist" || echo "not exist"
not exist
7、for循环语句
for((a,b,c));do...;done
[root@localhost ~]# for ((i=0;i<10;i++));do echo $i;done
0
1
2
3
4
5
6
7
8
9

[root@localhost ~]# array=(1 2 3 4 5)
#数组的长度
[root@localhost ~]# for((i=0;i<${#array[@]};i++));do echo $i;done
0
1
2
3
4

#for的遍历循环
[root@localhost ~]# for i in ${array[@]};do echo $i;done
1
2
3
4
5
[root@localhost ~]# for i in $(seq 1 10);do echo $i;done
1
2
3
4
5
6
7
8
9
10
#注意ls是被反引号括起来,反引号在esc按键下方
[root@localhost ~]# for i in `ls`;do echo $i;done
1.sh
2.sh
anaconda-ks.cfg
cmdline
demo
8、while循环语句
while   判断语句 
	do
		执行语句
	done
9、退出控制
  • return函数返回
  • exit脚本进程退出
  • break退出当前循环
  • continue跳过当前的循环
10、shell运行环境
  • ()表示在子shell中运行 ,也就是在子进程中运行。
  • {}表示在shell中执行
  • $$当前脚本执行的pid
  • &后台执行
  • &!运行在后台的最后一个作业的PID(进程ID)
11、程序前后台切换
  • 在命令末尾加上 & 符号,就可以让程序在后台运行
[root@localhost ~]# sleep 100&
[2] 9743
  • 如果程序正在前台运行,可以使用 Ctrl+z 选项把程序暂停
[root@localhost ~]# sleep 100
^Z[1]   完成                  sleep 110

[3]+  已停止               sleep 100
  • bg %[number] 命令把这个程序放到后台运行
[root@localhost ~]# jobs
[2]-  完成                  sleep 100
[3]+  已停止               sleep 100
[root@localhost ~]# bg 3
[3]+ sleep 100 &

数字为3的进程已经停止,此时可以用bg 3将其调用到后台继续运行

  • 对于所有运行的程序,可以用jobs –l 指令查看
[root@localhost ~]# jobs -l
[3]+  9744 完成                  sleep 100
  • 也可以用 fg %[number] 指令把一个程序掉到前台
[root@localhost ~]# jobs -l
[1]+  9745 停止                  sleep 100
[root@localhost ~]# bg 1
[1]+ sleep 100 &
[root@localhost ~]# fg 1
sleep 100
  • kill终止后台运行的程序
[root@localhost ~]# jobs
[1]+  已停止               sleep 100
[root@localhost ~]# kill %1

[1]+  已停止               sleep 100
[root@localhost ~]# jobs
[1]+  已终止               sleep 100
12、shell输入输出重定向
  • “>”表示将结果输出至某个文件,若文件中有内容,那么内容将会被覆盖,示例如下:
[root@localhost ~]# cat test
hello to testerhome
hello form testerhome
[root@localhost ~]# echo "ni hao" > test
[root@localhost ~]# cat test
ni hao
  • “>>”表示将结果追加至某个文件,若文件中有内容,结果将追加至内容之后,不会覆盖原来的文件内容,示例如下:
[root@localhost ~]# cat test
ni hao
hello world
[root@localhost ~]# echo "this is a test" >> test
[root@localhost ~]# cat test
ni hao
hello world
this is a test
  • "2>"表示将错误信息输入至某个文件。

  • "&>"表示不管正确与否都将信息输入至某个文件。

  • |表示管道,也就是前一个命名的输出传入下一个命名的输入

  • < file输入重定向

  • 1>&2 意思是把标准输出重定向到标准错误.

    2>&1 意思是把标准错误输出重定向到标准输出。

    &>filename 意思是把标准输出和标准错误输出都重定向到文件filename中

13、三剑客之grep

定义:数据查找定位,基于正则表达式查找满足条件的行

  • 忽略大小写进行定位查找
grep -i pattern file
  • 把每个匹配到的内容独立的行显示,只显示匹配到的内容
grep -o pattern file
  • 不显示匹配的行
grep -v pattern file
  • 使用扩展正则表达式
grep -E pattern file
  • 递归搜索
grep pattern file -r dir
  • 打印命中数据的上下文
grep -A -B -C pattern file
14、三剑客之awk

定义:数据切片,根据定位到的数据行处理其中的分段,与python中的元素分割类似

  • 开始和结束
awk 'BEGIN{}END{}'
  • 正则匹配
awk '/Running/'
  • 区间选择
awk '/aa/,/bb/'

示例:取15至19区间的数字

[root@localhost ~]# seq 20 | awk '/15/,/19/'
15
16
17
18
19
  • -F字段匹配
[root@localhost ~]# echo "123|456|789" | awk -F '|'  '{print $2}'
456
[root@localhost ~]# echo "123|456|789" | awk -F '|'  '{print $1}'
123
[root@localhost ~]# echo "123|456|789" | awk -F '|'  '{print $0}'
123|456|789

[root@localhost ~]# echo "123_456+789" | awk -F '+|_'  '{print $0}'
123_456+789
[root@localhost ~]# echo "123_456+789" | awk -F '+|_'  '{print $1}'
123
[root@localhost ~]# echo "123_456+789" | awk -F '+|_'  '{print $2}'
456
[root@localhost ~]# echo "123_456+789" | awk -F '+|_'  '{print $3}'
789

#最后登录的4个用户
[root@localhost ~]# last -n 4
root     pts/2        192.168.158.1    Wed Dec 11 13:53   still logged in   
root     pts/1        192.168.158.1    Wed Dec 11 12:40 - 15:53  (03:12)    
root     pts/0        192.168.158.1    Wed Dec 11 09:01 - 14:40  (05:39)    
root     pts/0        192.168.158.1    Tue Dec 10 09:31 - 14:37  (05:06)    

[root@localhost ~]# last -n 4 | awk '{print $3}'
192.168.158.1
192.168.158.1
192.168.158.1
192.168.158.1

#i++可以显示行号,方便查询
[root@localhost ~]# awk -F "'" '/^menu/{print $2}' /boot/grub2/grub.cfg
CentOS Linux (3.10.0-1062.9.1.el7.x86_64) 7 (Core)
CentOS Linux (3.10.0-957.el7.x86_64) 7 (Core)
CentOS Linux (0-rescue-27ff2a8edea7471692d8fb69998db98d) 7 (Core)

[root@localhost ~]# awk -F "'" '/^menu/{print i++,$2}' /boot/grub2/grub.cfg
0 CentOS Linux (3.10.0-1062.9.1.el7.x86_64) 7 (Core)
1 CentOS Linux (3.10.0-957.el7.x86_64) 7 (Core)
2 CentOS Linux (0-rescue-27ff2a8edea7471692d8fb69998db98d) 7 (Core)
[root@localhost ~]# 

  • 字段匹配
awk '$2~/xxx/'
  • 取第二行
awk 'NR==2'

示例:取第二行的数据

[root@localhost ~]# seq 20 | awk 'NR==2'
2
  • 去掉第一行
awk 'NR>1'

示例:去掉标题行

[root@localhost ~]# vmstat
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 1  0      0 482620  23508 330220    0    0     1     0   23   42  0  0 100  0  0

[root@localhost ~]# vmstat | awk 'NR>1'
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 1  0      0 482396  23508 330220    0    0     1     0   23   42  0  0 100  0  0
  • RS记录分割符,或者是行分隔符
[root@localhost ~]# echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin:/root/xyz

[root@localhost ~]# echo $PATH | awk 'BEGIN{RS=":"}{print $0}'
/usr/local/sbin
/usr/local/bin
/usr/sbin
/usr/bin
/root/bin

[root@localhost ~]# echo $PATH | awk 'BEGIN{RS=":"}{print $1}' | awk -F "/" '{print $1, $2 $3 $4}'
 usrlocalsbin
 usrlocalbin
 usrsbin
 usrbin
 rootbin
 rootxyz
 
[root@localhost ~]# echo $PATH | awk 'BEGIN{RS=":"}{print $1}' | awk -F "/" '{print $1,$2,$3,$4}'
 usr local sbin
 usr local bin
 usr sbin 
 usr bin 
 root bin 
 root xyz

将PATH变量用“:”进行分割。

  • FS字段分隔符
[root@localhost ~]# echo '1|2#3_4'
1|2#3_4
[root@localhost ~]# echo '1|2#3_4' | awk 'BEGIN{FS="#|_|\\|"}{print $0}'
1|2#3_4
[root@localhost ~]# echo '1|2#3_4' | awk 'BEGIN{FS="#|_|\\|"}{print $1}'
1
[root@localhost ~]# echo '1|2#3_4' | awk 'BEGIN{FS="#|_|\\|"}{print $2}'
2
[root@localhost ~]# echo '1|2#3_4' | awk 'BEGIN{FS="#|_|\\|"}{print $3}'
3
[root@localhost ~]# echo '1|2#3_4' | awk 'BEGIN{FS="#|_|\\|"}{print $4}'
4

用#|_符号分割'1|2#3_4'字符串

  • OFS输出数据的字段分隔符
[root@localhost ~]# echo '1|2#3_4' | awk 'BEGIN{FS="#|_|\\|"}{print $1,$2,$3,$4}'
1 2 3 4

[root@localhost ~]# echo '1|2#3_4' | awk 'BEGIN{FS="#|_|\\|";OFS="_"}{print $1,$2,$3,$4}'
1_2_3_4

OFS输出数据默认是空格进行分割,OFS可以指定分割的符号,比如上例中的下划线“_”符号进行分割。

  • ORS输出字段的行分隔符
[root@localhost ~]# echo '1|2#3_4' | awk 'BEGIN{RS="#|_|\\|"}{print $1}'
1
2
3
4
[root@localhost ~]# echo '1|2#3_4' | awk 'BEGIN{RS="#|_|\\|";ORS=":"}{print $1}'
1:2:3:4:[root@localhost ~]#

[root@localhost ~]# echo $PATH | awk 'BEGIN{RS=":"}{print $0}'
/usr/local/sbin
/usr/local/bin
/usr/sbin
/usr/bin
/root/bin
/root/xyz

[root@localhost ~]# echo $PATH | awk 'BEGIN{RS=":"}{print $0}' | awk 'BEGIN{FS="\n";ORS=":"}{print $0}'
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin:/root/xyz::[root@localhost ~]# 

ORS输出字段的行分隔符默认是换行符“\n”,上例中改变分隔符为":"冒号时,可以将输出字段拼接成一行。

  • NR记录数
[root@localhost ~]# echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin:/root/xyz

[root@localhost ~]# echo $PATH | awk 'BEGIN{RS=":"}{print NR,$0}'
1 /usr/local/sbin
2 /usr/local/bin
3 /usr/sbin
4 /usr/bin
5 /root/bin
6 /root/xyz

#加END后,统计总的行数
[root@localhost ~]# echo $PATH | awk 'BEGIN{RS=":"}END{print NR}'
6

[root@localhost ~]# echo $PATH | awk 'BEGIN{RS=":"}{print NR}'
1
2
3
4
5
6

[root@localhost ~]# echo $PATH | awk 'BEGIN{RS=":"}{print NR,$0}'
1 /usr/local/sbin
2 /usr/local/bin
3 /usr/sbin
4 /usr/bin
5 /root/bin
6 /root/xyz

#输出最后一行
[root@localhost ~]# echo $PATH | awk 'BEGIN{RS=":"}END{print NR,$0}'
6 /root/xyz
  • 数字的计算

比如:请利用bash自动输出2、5、8,并求和

1|2|3
4|5|6
7|8|9
echo -e "1|2|3\n4|5|6\n7|8|9" | awk -F '|' 'BEGIN{a=0}{a=a+$2;print $2}END{print a}'

结果:

2
5
8
15

比如:乘除法计算

[root@localhost ~]# awk 'BEGIN{print 1/3}'
0.333333
[root@localhost ~]# awk 'BEGIN{printf "%.2f\n",1/3}'
0.33
[root@localhost ~]# awk 'BEGIN{printf "%.3f\n",1/3}'
0.333
[root@localhost ~]# awk 'BEGIN{printf "%.4f\n",1/3}'
0.3333
[root@localhost ~]# awk 'BEGIN{printf "%.4f",1/3}'
0.3333[root@localhost ~]# 

比如:计算前数据之和

[root@localhost ~]# seq 10 2 20
10
12
14
16
18
20
[root@localhost ~]# seq 10 2 20 | awk '{sum+=$1}{print sum}'
10
22
36
52
70
90

比如:求平均值

[root@localhost ~]# seq 10 2 20 | awk '{sum+=$1}{print sum/NR}'
10
11
12
13
14
15
15、三剑客之sed

定义:数据修改,根据定位到的数据行修改数据

  • 命令使用
sed 's/正则/结果/g'

正则:需要替换的内容
结果:替换成什么
g:替换所有
  • 修改替换数据

例如:将test2.txt中的haha替换为hello

命令:

[root@localhost ~]# sed -i 's/haha/hello/' test2.txt 

示例:

[root@localhost ~]# cat test2.txt 
haha world
haha from testerhome
HELLO TO TESTERHOME
hha
huhu

[root@localhost ~]# sed -i 's/haha/hello/' test2.txt 
[root@localhost ~]# cat test2.txt 
hello world
hello from testerhome
HELLO TO TESTERHOME
hha
huhu

示列:返回一个 IP 数组,并且按 IP 最后一位排序返回。

str='192.169.32.1?!289.0.0.3!192.168.0.11?192.163.10.18?!192.168.5.4'

解答:

#方法一:-n代表升序排列,-r代表降序排列
[root@localhost ~]# array=`echo $a | sed 's/[?!]/\n/g'|sort -t "." -k 4 -n`
[root@localhost ~]# echo ${array[@]}
192.169.32.1 289.0.0.3 192.168.5.4 192.168.0.11 192.163.10.18

#方法二
[root@localhost ~]# array=`echo $str | awk -F '!|?|?!' '{print $1"\n"$2"\n"$3"\n"$4"\n"$5 }'|sort -n -t . -k 4`
[root@localhost ~]# echo $array
192.169.32.1 289.0.0.3 192.168.5.4 192.168.0.11 192.163.10.18

#方法三
[root@localhost ~]# echo $str
192.169.32.1?!289.0.0.3!192.168.0.11?192.163.10.18?!192.168.5.4
[root@localhost ~]# echo $str | awk '{split($0,a,"!|?");for (i in a) {print i,a[i]}}'
4 192.168.0.11
5 192.163.10.18
6 
7 192.168.5.4
1 192.169.32.1
2 
3 289.0.0.3

[root@localhost ~]# echo $str | awk '{split($0,a,"!|?");for (i in a) {print i,a[i]}}'|sort -nk 4 -t .
2 
6 
1 192.169.32.1
3 289.0.0.3
7 192.168.5.4
4 192.168.0.11
5 192.163.10.18

[root@localhost ~]# array=`echo $str | awk '{split($0,a,"!|?");for (i in a) {print a[i]}}'|sort -nk 4 -t .`

[root@localhost ~]# echo $array
192.169.32.1 289.0.0.3 192.168.5.4 192.168.0.11 192.163.10.18


  • 替换数据时备份,防止替换文件时出错。

命令:

[root@localhost ~]# sed -i.bak 's/haha/hello/' test2.txt 

示例:在修改文件后,会自动生成一个.bak的备份文件,注意(.bak)并非标准格式,可以根据需要随意设置备份文件格式。

[root@localhost ~]# cat test2.txt 
haha world
hha
huhu

[root@localhost ~]# sed -i.bak 's/haha/hello/' test2.txt 
[root@localhost ~]# cat test2.txt
hello world
hha
huhu

[root@localhost ~]# cat test2.txt.bak 
haha world
hha
huhu
  • 打印第几行

比如:打印第5行数据

sed -n '5p'
[root@localhost ~]# seq 1 10
1
2
3
4
5
6
7
8
9
10
[root@localhost ~]# seq 1 10 | sed -n '5p'
5

比如:打印5到9的数据

[root@localhost ~]# seq 1 10 | sed -n '5,9p'
5
6
7
8
9
  • 删除数据

比如:删除第二行数据

sed '2d'
[root@localhost ~]# seq 1 10 | sed '2d'
1
3
4
5
6
7
8
9
10
  • 取数据高级技巧
\1\2匹配的字段

比如:获取123至134的最后一位数,和后面两位数。比如123就获取3,再获取23。

[root@localhost ~]# seq 123 134
123
124
125
126
127
128
129
130
131
132
133
134

#匹配第三为数字,用括号括起来即表示要匹配的位置
[root@localhost ~]# seq 123 134 | sed -E 's/..(.)/\1/g'
3
4
5
6
7
8
9
0
1
2
3
4
#匹配第二位和第三位数字
[root@localhost ~]# seq 123 134 | sed -E 's/.(.)(.)/\1\2/g'
23
24
25
26
27
28
29
30
31
32
33
34
16、文件判断
[ -e dir|file ]
[ -d dir ] 是否存在,⽽而且是⽬目录
[ -f file ] 是否存在,⽽而且是⽂文件
[ -r file ] 读权限
[ -x file ] 执⾏行行权限
[ -w file ] 写权限

常见使用场景是备份数据库

#!/usr/bin/bash

#定义备份目录站点
back_dir=/var/mysql_back

# test -d $back_dir || mkdir -p $back_dir

if [ ! -d $back_dir ];then
	mkdir -p $back_dir
fi
echo "开始备份..."
17、执行shell
  • ./XXX.sh方式执行shell,注意其是在子进程中执行
  • bash XXX.sh方式执行shell,其也是在子进程中执行
  • source XXX.sh方式执行shell,注意其是在当前进程中执行
  • . XXX.sh方式执行shell,其是在当前进程中执行

示例:1.sh

#!/bin/bash

echo $demo_var
#当前进程中定义一个变量
[root@localhost ~]# demo_var="hello shell"
[root@localhost ~]# echo $demo_var 
hello shell
[root@localhost ~]# vi 1.sh
[root@localhost ~]# chmod u+x 1.sh

#第一种方式执行时无法获取当前进程中的变量值
[root@localhost ~]# ./1.sh 

[root@localhost ~]# bash 1.sh 

#source方式执行脚本时可以获取当前进程中的值
[root@localhost ~]# source 1.sh 
hello shell
[root@localhost ~]# . 1.sh
hello shell
[root@localhost ~]# 

#若要子进程中也能获取变量,需要用export将其导出
[root@localhost ~]# export demo_var
[root@localhost ~]# ./1.sh 
hello shell
[root@localhost ~]# bash 1.sh 
hello shell
[root@localhost ~]# source 1.sh 
hello shell
[root@localhost ~]# . 1.sh 
hello shell

#删除环境变量
[root@localhost ~]# unset demo_var
[root@localhost ~]# ./1.sh 

[root@localhost ~]# 
18、位置变量

注意第10个位置参数的写法

#!/bin/bash
#位置参数$1,$2...$9,${10}
para1=$1
#这样设置后,当第二个位置参数为空时将会打印出-,方便识别
para2=${2-_}

echo $para1
echo $para2

[root@localhost ~]# vi 2.sh
[root@localhost ~]# 
[root@localhost ~]# chmod u+x 2.sh
[root@localhost ~]# bash 2.sh -a -b
-a
-b
[root@localhost ~]# bash 2.sh -a
-a

[root@localhost ~]# vi 2.sh
[root@localhost ~]# bash 2.sh -a
-a

[root@localhost ~]# bash 2.sh -a -b
-a
-b
[root@localhost ~]# vi 2.sh
[root@localhost ~]# bash 2.sh -a -b
-a
-b
#当参数设置为para2=${2-_},第二个位置参数为空时,就能识别,否则为空不容易发现
[root@localhost ~]# bash 2.sh -a
-a
_
[root@localhost ~]# 

19、Shell输入输出
read (选项)(参数):从控制台读取数据
-p:指定读取值时的提示符
-t:指定读值的等待时间【单位:秒】,超时不等待

参数:指定读取值的变量名
#!/bin/bash

read -p "input a number:" NUM1
echo "num1=$NUM1"

read -t 5 -p "在5秒内,输入一个数num=" NUM2
echo "num=$NUM2"
20、Linux定时任务调度

crond任务调度
系统在某个时间段执行特定的命令或程序。

1、数据库的定时备份操作。

2、系统一些重复工作,病毒扫描等。

用法

crontab 【选项】

-e:编辑crontab定时任务

-l:查询crontab任务

-f:删除当前用户所有的crontab任务

-r:终止任务调度

service crond restart:重启任务调度

crontab -e
*/1 * * * * ls -l /etc > /tmp/to.txt  -- 每小时的每分钟执行

第一个*:一小时中的第几分钟【0-59】

第二个*:一天中的第几个小时【0-23】

第三个*:一个月当中的第几天【1-31】

第四个*:一年中的的第几月【1-12】

第五个*:一周当中对的星期几【0-7 0和7都表示 周日】

21、同时显示两个文件的差异
diff -c file1 file2

以并列的方式显示两个文件的差异

diff -y file1 file2
posted @ 2020-02-25 18:03  xyztank  阅读(95)  评论(0)    收藏  举报