一、shell 变量

  1、自定义局部变量

#等号两端不能有空格
var_name=liming
#打印变量值
echo $var_name
#使用花括号可以用于字符串拼接
echo ${var_name}123
#删除变量
unset $var_name

  2、自定义常量

var_name=liming
#设置为只读
readonly var_name

  3、自定义全局变量

    局部变量只能在一个文件中使用,全局变量在当前脚本文件和子shell脚本文件中都可以使用。

export var_name=jenny
#删除
unset var_name

  4、特殊符号变量

    $n

#获取文件名
${0}
#获取第一个输入参数
${1}
...
#获取第十个输入参数
${10}

    $#:获取输入参数的个数;

    $*和$@:获取所有输入参数;区别:在有双引号时,“$*”将列表参数组成一个字符串,“$@”一个参数是一个字符串。可以使用for循环验证。

for var in "$@"
do
     echo ${var}
done

    $?:获取上一个shell命令的退出状态码或者是退出值。每一个shell命令都有一个返回值,用来表示命名是否执行成功,一般“0”表示成功。

    $$:获取shell进程号。

  5、自定义系统环境变量

    当前用户进入shell环境初始化时会加载全局配置文件/etc/profile里面的环境变量,供给所有shell程序使用。只要是所有shell程序都可能使用的变量都可以放在/etc/profile文件中。

    创建环境变量步骤:vim打开/etc/profile文件,添加export  VAR_NAME=value,保存退出,使用source  /etc/profile重新加载。

    shell工作环境分类

      1)交互式shell环境:需要用户参与互动的shell环境;

      2)非交互式shell环境:只执行命令。

      3)登录shell环境:需要输入用户名和密码登录到系统,会首先执行/etc/profile/配置文件加载环境变量,使用命令echo $0可以查看是否是登录环境,如果输出-bash,说明是登录环境,如果输出bash说明是非登录环境。命令"su  用户名 "可切换至非登录环境。

      4)非登录shell环境:不使用用户名和密码进入Linux系统,会首先执行~/.bashrc。命令"su  用户名 -l"可切换至登录环境。

   6、字符串截取

VAR1=Jenny
#${变量名:start:len}
#从0开始截取两个,输出Je
echo ${VAR1:0:2}
#${变量名:start}输出nny
echo ${VAR1:2}
#${变量名:0-start:len} 表示从右侧的第start各元素开始,向右截取len个
#输出 ny
echo ${VAR1:0-2:2}
#${变量名#*char},从左侧开始截取第一次出现char字符的右侧所有字符串
#nny
echo ${VAR1#*e}
#${变量名##*char},从左侧开始截取最后一次出现char字符的右侧所有字符串
#y
echo ${VAR1##*n}
#${变量名%*char},从右侧开始截取第一次出现char字符的右侧所有字符串
#${变量名%%*char}。从右侧开始截取最后一次出现char字符的右侧所有字符串

二、shell内置命令

  shell的命令分为内置命令和外部脚本执行文件。内置命令属于shell内部,执行速度块。外部脚本文件需要磁盘I/O操作并fork一个新进程,执行速度相对慢。

  1、alias给命令起别名

alias  别名=命令
#取消别名
unalias 别名

  2、echo输出字符串

#输出不换行
echo  -n  "hello"
#输出换行
echo  "hello"
#解析转义字符
echo  -e  "hello\n"

  3、read从标准输入中获取数据并赋值给变量。默认从终端控制台中读入,可以使用重定向从文件中读取。

           1)read -p 提示 变量

#-p表示显示提示信息
read -p "please input name age hobby"  name age hobby
echo "name=${name}"
echo "age=${age}"
echo "hobby= ${hobby}"

    2)read -n num 变量 指定该读取num个字符到变量中

      3) read -t  秒数 变量  设置超时时间

      4)read  -s 静默模式,不会在屏幕上显示

#在15秒内输入
read -t 15 -sp "please input pwd :"  pwd1
echo
read -t 15 -sp "please input pwd again : " pwd2
echo
if [ $pwd1 == $pwd2 ]
then
     echo "ok"
else
     echo "no"
fi

  4、exit

    退出当前shell进程,并返回状态码。

  5、declare

    declare -a 数组名=( 元素1 元素2 元素3)   -a参数指定创建普通索引数组

    declare -A 数组名=(["key1"]=value1 ["key2"]=value2 ["key3"]=value3) -A参数指定创建关联式数组

echo "创建索引数组"
declare -a arry1=( 101 "liming" 20 )
echo "获取arry1中第一个元素:" ${arry1[0]}
echo "获取arry1中所有元素:" ${arry1[*]}
echo 
echo "创建关联数组"
declare -A arry2=(["id"]=101 ["name"]="liming" ["age"]=20)
echo "获取arry2中key为id对应的value:" ${arry1["id"]}
echo "获取arry2中所有元素:" ${arry1[@]} 

  declare设置变量属性:declare  [+/- aArixf] 变量名=变量值

三、shell运算符

  1、expr求值表达式

    result=`expr 1+5`

read -p "please input first num:" a
read -p "please input second num:" b
echo "first num is:${a}"
echo "second num is:${b}"
echo "a+b=`expr $a + $b`"
echo "a-b=`expr $a - $b`"
echo "a*b=`expr $a \* $b`"
echo "a/b=`expr $a / $b`"
echo "a%b=`expr $a % $b`"

  2、比较运算符

    整数比较,假设a=1;b=2

运算符 说明 举例
-eq   判断两边的数是否相等,相等返回0,不等返回1 [ $a -eq $b ] 返回1
-ne 判断两边的数是否不相等,不相等返回0,相等返回1 [ $a -ne $b ] 返回0
-gt 判断左边是否大于右边 [ $a -gt $b ] 返回1
-lt    判断左边是否小于右边 [ $a -lt $b ] 返回0 
-ge 判断左边是否大于等于右边 [ $a -ge $b ] 返回1
-le 判断左边是否小于等于右边 [ $a -le $b ] 返回0

    字符串比较,a="abc";b="ab"

运算符 说明 举例
==/= 判断两个字符串是否相等

[[ $a == $b]]

[ $a == $b ]

> 判断左边边是否大于右边

[[ $a > $b ]]

[ $a \> $b ]

< 判断左边是否小于右边

[[ $a < $b ]]

[ $a \< $b ]

!= 判断两个字符串是否不相等

[[ $a != $b ]]

[ $a != $b ]

-z 字符串长度是否为0 [ -z $a ]
-n 字符串长度是否不为0 [ -n $a ]

  3、布尔运算符

符号 说明 举例
非运算。取反 [ ! 表达式 ]
-o 或运算,一方为真,则为真 [ 表达式1 -o 表达式2 ]
-a 与运算 [ 表达式1 -a 表达式2 ]

  4、逻辑运算符

符号 说明 举例
&& 逻辑AND [[  1>2 && 1 == 1 ]] 返回1
|| 逻辑 OR [[ 1>2 || 1 == 1 ]] 返回0
!   逻辑非 [[ ! 1>2 ]] 返回0

  5、文件检测运算符

符号 说明 举例
-d file 检测文件是否是目录,返回true或者fasle [ -d $file ] 
-f file 检测文件是否是普通文件,返回值同上 [ -f $file ]
-r file 检测文件是否可读,返回值同上 [ -r $file ]
-w file 检测文件是否可写 [ -w $file ]
-x file 检测文件是否可执行 [ -x $file ]
-e file 检测文件是否存在 [ -e $file ]
-s file 文件是否为空,如果文件大小不为空(size>0)返回true [ -s $file ]

四、shell计算命令

  1、expr表达式求值

    1)expr length 字符串;求字符串的长度;

    2)expr substr 字符串 start end ;截取字符串

#返回 hello
expr substr hellokitty 1 5

      3)获取第一个字符在字符串中的出现位置:expr index 字符串  字符

#输出5
expr index hellokitty o

  2、(())

    1)括号内赋值:((a=1+2))

    2)括号外赋值:b=$((a+2))

    3)多表达式赋值:((c=a+b,d=1+3,e=c+2))

    4)与if条件配合使用:if ((a==b || a==c))

  3、let用于赋值操作

     let  a=1+2

     let  b = 1+2  c= 1+3

  4、$[]与(())、let类似,只能进行整数运算。$[]只能对单个表达式的计算求值和输出

      a=$[1+1]

      b=$[a+1]

      echo "$[a+b]"

五、控制语句

  1、if...else语句

if  [ 条件1 ]
then
     命令1
elif [ 条件2 ]
then
     命令2
else
     命令3
fi        

  2、case

case  值  in
匹配模式1)
    命令 
    ...
    ;;
匹配模式2)
    命令
     ...
     ;;
*)
    命令
     ...
     ;;
esac

   3、while

while  条件
do
        命令1
        命令2
        ...
        continue#结束本次循环,进入下一次循环
        break; #跳出循环
done

  4、until

#条件为false才进入循环
until  条件
do
  ...
done

  5、for

#var是循环变量,item是循环的范围
for  var  in item1 item2 ... itemN
do
   ...
done

    另外一种for循环

for((i=0;i<10;i++))
do 
   echo "hello${i}"
done

    无限循环

for((;;));do 命令...;done

  6、select

select var  in menu1 menu2 ...
do 
    命令
done

    select 是无线循环,输入空或者输入无效值都不能结束循环,知道遇到break才结束循环。

    终端输入#?表示可以输入选择的菜单编号。

一个demo

  1 #! /bin/bash
  2 echo "please input your hobby"
  3 select hobby in "shell coding" "reading" "basketball" "delicious food"
  4 do
  5     case $hobby in
  6         "shell coding")
  7             echo "good boy"
  8             break
  9             ;;
 10          "reading")
 11             echo "Excellent people"
 12             break
 13             ;;
 14          "basketball")
 15             echo "good for health"
 16             break
 17             ;;
 18          *)
 19             echo "???"
 20 esac
 21 done

六、系统函数

  1、basename系统函数,根据给出的文件路径获取文件名。

    basename  ~/ex/shell/select.sh

    输出 select.sh

    basename ~/ex/shell/select.sh  .sh

    输出select

  2、dirname系统函数,根据给出的文件路径取除文件名,取出路径。

    dirname  ~/ex/shell/var/demo.sh

    输出/home/tx/shell/var

  3、自定义函数

函数名()
{
    函数体
}
#函数调用
函数名  参数1 参数2 参数3.....
f1(){

#$0获取文件名
echo $0
#$1获取函数第一个参数
echo $1
#$2获取函数第二个参数
echo $2
return 1;
}
#$0获取文件名
echo $0
#$1获取文件的第一个输入参数
echo $1
#$2获取文件的第二个输入参数
echo $2
#给函数传参
f1 aa bb

  函数与shell程序的区别:shell 程序运行时会开启一个子进程,函数是在当前shell进程中运行,不会开启子进程。

七、文件重定向

命令 说明
cmd>file 将正确的输出重定向到file中,会覆盖原有数据
cmd>>file 将正确的输出重定向到file中,以追加方式
cmd >>file 2>&1 正确输出和错误输出都重定向到file中
cmd <file 从file中读取数据  例如:wc-l log.txt

 八、shell好用的工具

  1、cut切割提取指定列/字符/字节的数据。

    语法

cut  [options]  filename

    options参数说明

选项参数 功能
-f  提取范围 列号,获取第几列
-d 自定义分隔符 自定义分隔符
-c 提取范围 以字符为单位进行分割
-b 提取范围 以字节为单位进行分割,与-n连用
-n 与-b连用,不分割多字节字符

    提取范围说明

提取范围 说明
n- 提取指定第n列/字节/字符后面所有的数据
n-m 提取指定第n列/字符/字符到第m列/字符/字符中间的所有数据
-m 提取指定第m列/字节/字符之前的所有数据

    demo1

    原始数据

    10001  liming  陕西

    10002  jenny  湖南

    10003  denny  西雅图

    获取第一列数据:cut   filename  -d " " -f 1

       获取第二列数据:cut   filename  -d " " -f 3

    获取第一列数据:cut   filename  -d " " -f 5

    获取前两个字符:cut  filename -c 1-2

    切割出“jenny”  :cat filename | grep "jenny" | cut -d " " -f 3

  2、sed

    stream editor (流编辑器)是非交互式流式文本编辑器,可以对文本文件的每一行数据匹配查询之后进行增、删、改、查等操作。

    sed数据处理工作原理

    语法

#只有符合模式匹配的数据才执行sed命令
sed  [options]  [模式匹配/sed程序命令]  [文件名]

    sed命令

命令 功能描述
a 向匹配行后面添加数据
i 向匹配行前面插入数据
d 删除匹配行的数据
c 更改匹配行的内容
s 替换匹配行内容
p 打印出匹配的内容,与选项-n连用
n 读取下一行,遇到n会自动跳入下一行
= 打印被匹配行的行号

    实战:

    1)向文件中添加数据

      向指定行号的前或者后添加数据

sed  '2ahow' sed.txt
sed  '2ihow' sed.txt

      向指定内容前或者后添加数据

sed '/kitty/acat' sed.txt
sed '/kitty/icat' sed.txt

      在最后一行前或者后添加数据

sed '$ahow are you' sed.txt
sed '$ihow are you' sed.txt

    2)删除文件中的数据  

#删除第二行
sed  '2d'  sed.txt
#删除奇数行。从第一行开始,每隔两行
sed '1~2d' sed.txt
#删除从第一行到第三行数据
sed '1,3d' sed.txt
#删除最后一行
sed '$d' sed.txt
#删除匹配“hello”的行
sed '/hello/d' sed.txt
#删除匹配行到最后一行
sed '/hello/,$d' sed.txt
#删除匹配行及后面一行
sed '/hello/,+1d' sed.txt
#删除不匹配的行,除kitty ,hello之外全部删除
sed '/kitty\|hello/d' sed.txt

    3)更改文件中的数据

#文件中的第一行改为“ABC"
sed '1cABC' sed.txt
#将包含hello的行改为world
sed ‘/hello/cworld’ sed.txt
#将最后一行改为GO TO SCHOOL
sed '$cTO GO SCHOOL' sed.txt
#将hello替换为HELLO,默认只替换每一行的第一个
sed 's/hello/HELLO' sed.txt
#将所有hello替换为HELLO
sed 's/hello/HELLO/g' sed.txt
#替换每一行的第2个hello
sed 's/hello/HELLO/2' sed.txt
#将替换后的内容写入文件
sed 's/hello/HELLO/2w sed2.txt' sed.txt
#只打印修改的行
sed -n 's/hello/HELLO/2p' sed.txt
#每行末尾拼接一个test
sed 's/$/& test/' sed.txt
#每行行首添加一个”#“
sed 's/^/$#/' sed.txt

    4)查询

#查询含有kitty的行数据
sed -n '/kitty/p' sed.txt
#查询所有bash进程
ps aux | grep bash 
ps aux | sed  -n '/bash/p' 
#执行多个命令,删除第一行数据并替换hello
sed -e '1d' -e 's/hello/HELLO/g' sed.txt
#另外一种执行多命令
sed '1d;s/hello/HELLO/g' sed.txt

    5)缓冲区数据的交换

     sed处理数据是逐行处理,即读取一行处理一行输出一行。sed从文件中读出的一行存放的空间叫模式空间,此外sed还有另外一个缓冲区叫暂存空间,暂存空间刚开始里面只有一个空行。sed可通过命令从模式空间往暂存空间放入内容,或者从暂存空间中取内容放到模式空间。

命令 含义
h 将模式空间的内容放入暂存空间,以覆盖方式
H 将模式空间的内容放入暂存空间,以追加方式
g 将暂存空间的内容放入模式空间,以覆盖方式
将暂存空间的内容放入模式空间,以追加方式
x 交换两个空间的内容

    例题1,将第一行数据粘贴到最后一行

      思路:将模式空间中的第一行数据放入暂存空间,一覆盖方式,再从暂存空间把数据放入模式空间,以追加方式。

sed '1h;$G' sed.txt

    例题2,将第一行数据复制粘贴到其他行

      思路:将模式空间中的第一行数据放入暂存空间,以覆盖方式,然后再从暂存空间把数据放入模式空间中替换其他行的数据,以覆盖方式

sed '1h;2,$g' sed.txt

    例题3,将前三行数据复制粘贴到最后一行。

sed  '1,3H;$G'  sed.txt

    例题4,给每一行添加空行

#-i表示反应到文件本身
sed  -i 'G' sed.txt

    例题5,删除空行

sed  -i  '/^$/d' sed.txt

  3、awk

    一种文本分析工具,awk把文件逐行读入,以空格为默认分隔符将每行切片,切出的部分可以进行各种分析处理。

    语法:awk  options  '匹配模式{命令}'  filename

    参数说明:

选项参数 功能
-F 自定义分隔符
-v 赋值一个用户定义变量

    awk内置变量

内置变量 含义
ARGC 命令行参数个数
ARGV 命令行参数排列
FILENAME awk浏览的文件名
NF     根据分隔符分割后的列数
NR     行号
$n $0指整行记录,$1当前行的一列,$2指当前行的第二列.....
$NF 最后一列信息

 

#打印/etc/passwd第二行数据
awk -F: 'NR==2{printf("文件名:%s,行号:%s,内容:%s\n",FILENAME,NR,$0)}' passwd_copy
#查找以a开头的数据
ls -a| awk '/^a/'
#打印第一列
awk -F: '{print $1}' passwd_copy
#打印最后一列
awk  -F: '{print $NF}' passwd_copy
#打印倒数第二列
awk -F: '{print $(NF-1)}' passwd_copy
#打印10到15行的第1列
awk -F: '{if(NR>=10&&NR<=15){print $1}}' passwd_copy 
#多分割符
acho  "123:asd/lli"| awk -F '[:/]' '{print $1}'
#在文件头尾添加内容
echo -e "abc\nabc" | awk 'BEGIN{print "----开始----"}{print$0}END{print "---结束---"}'
#使用循环拼接分割后的字符串
echo "liming            jenny denny" | awk -v str="" '{for(n=1;n<=NF;++n){str=str$n} END{print str}}'
#进行运算
echo "2.2" | awk '{print $0+1}'
#获取ip
#inet 192.168.31.119  netmask 255.255.255.0  broadcast 192.168.31.255
#方式1:
ifconfig | awk '/broadcast/{print $0}'| awk '{print $2}'
#方式2,先指定第二行
ifconfig | awk 'NR==2{print $0}'| awk '{print $2}'

  4、sort

    将文件进行排序,并将排序结果标准输出或者重定向输出到指定文件。

    语法:sort  options  file

选项 说明
-n  安装数值大小排序
-r 以相反顺序排序
-t 分割字符 指定排序时所用的分隔符
-k 指定需要排序的列
-o 将排序后的结果存入指定文件

    sort对字符串升序或者降序

    sort  -kstart,end  file

    sort  -kstartr,end file

    sort对数字升序或者降序

    sort -kstartn,end file

    sort  -kstartnr,end file