shell编程

1.shell简介

Shell就是一种命令解析器,解析用户的命令调用系统内核执行相关的命令:比如我们写一个mkdir—>经过shell解析成Linux能看懂的2进制–>linux执行.一个系统可以存在多个shell,可以通过cat /etc/shells命令查看系统中安装的shell,不同的shell可能支持的命令语法是不相同的.

Shell也是一门编程语言,即shell脚本,shell是解释执行的脚本语言,可直接调用linux命令。Shell脚本的本质,就是大量shell命令的组合,并写入一个文本文件中!

shell1 mkdir ---- > 10101

shell2 md----> 10101

2. 脚本执行

创建脚本

vi helloworld.sh

#脚本以#!/bin/bash开头(指定解析器)

#!/bin/bash
echo "hello world"
touch 1.txt 2.txt 3.txt
ls -l > 1.txt

执行脚本

第一种方式 分配执行权
chmod u+x helloworld.sh
./helloworld.sh
/mysh/helloworld.sh
第二种方式 可以没有执行权 
bash  helloworld.sh
sh hellowrold.sh

3.变量

3.1 系统变量

使用set可以查看所有系统变量

BASH=/bin/bash
HOME=/root
HOSTNAME=linux01
JAVA_HOME=/opt/apps/jdk1.8.0_191
PATH=/usr/local/sbin:/usr/local

3.2 自定义变量

变量定义 
	变量名=变量值  #注意不能有空格
删除变量 
	unset 变量名 
声明常量 readonly变量,不能使用unset变量

name=zss
name=lss  改值
age=23
gender=M
readonly  USERNAME=Ly 不可变的变量  常量 

取值 
$name
${name}
"$name" 
'$name' ---> $name的字符串
注意字符串的拼接

echo $name    lss
echo ${name}  lss
echo "$name"aaa lssaaa  ""号中取变量的值可以正常取出  
echos '$name'aaa  $nameaaa ''号中取不出来变量的值 就是$name字符串 单引号会将所有特殊字符脱意



删除只读变量 (了解)
yum -y install gdb 

cat << EOF|gdb
attach $$
call unbind_variable("username")
detach
EOF
unset username

3.3 export和source

export  username=lisi 将变量的范围作用在所有的子bash中
source  将子bash定义的变量 作用在当前bash   

export 修饰的变量的作用域是 当前和所有的子进程
source 将子进程中的变量    拉取到当前

3.4 特殊变量

$1  $2  $n  ${10}  接收单个参数
$*   接收所有参数 
$@   接收所有参数
$#   参数的个数 
$?    接收上个命令执行的结果  0 执行成功   非0的是执行失败 
接收单个参数  一直到$9都可以 10以上 ${10}
vi args01.sh
#!/bin/bash
echo "接收的所有参数$1 $2 $3"
touch $1 $2 $3 

sh args01.sh 1.txt 2.txt 3.txt
接收所有参数
$*   接收所有参数 
$@   接收所有参数
$#   参数的个数
$?    接收上个命令执行的结果  0 执行成功   非0的是执行失败 

vi args02.sh

#!/bin/bash
echo "接收参数的个数$*"
echo "接收参数的个数$#"
touch $*

#!/bin/bash
echo "接收参数的个数$@"
echo "接收参数的个数$#"
touch $@

sh args02.sh 1.java 2.java

3.5 read交互

#!/bin/bash
read -t 10 -p '请输入您的用户名:' username   #username用来接收用户输入的用户名  -t 10代表10秒不输退出
read -t 10 -p '请输入您的密码:' password
echo "$username"
echo "$password"

3.6 算数运算

expr 1+1   # 错误  1 + 1 之间必须有空格
expr 1 + 1  
expr 1 + 1 \* 2 由于*有特殊含义 需要转义 
expr `expr 1 + 2` \* 3

$((1+1))  
$(((1+2)*3))
$[1+1]
$[(1+2)*3]


${a}  取变量a的值
$() 取一个命令的结果  
$(( )) 取算术运算表达式的运算结果  $[]相同

4.条件判断

4.1 &&和||

&&:用来执行条件成立后执行的命令
||:用来执行条件不成立后的执行命令

ping windows && echo yes || echo no    windows能ping通 输出yes 不能ping通输出no
ls && echo yes || echo no  ls执行成功 输出yes 执行不成功输出no

4.2 整数测试

注意 符号 两边要有空格
test 1 = 1 && echo yes || echo no 			 1 == 1
test 1 != 1 && echo yes || echo no 		 	 1 != 1
test 1 -eq  1 && echo yes || echo no 		 1 == 1
test 1 -ne  1 && echo yes || echo no 		 1 != 1
test 1 -gt  2 && echo yes || echo no 		 1 >  2
test 1 -lt  2 && echo yes || echo no 		 1 <  2
test 1 -ge  2 && echo yes || echo no 		 1 >= 2
test 1 -le  2 && echo yes || echo no 		 1 <= 2


a=1
b=2
test $a = $b  && echo yes || echo no 
test $a != $b  && echo yes || echo no 

test $a   && echo yes || echo no  a存在 输出 yes  不存在输出 no

test $a -a $a = 1   && echo yes || echo no       yes
test $a -a $a = 2   && echo yes || echo no       no
test $a -o $a = 2   && echo yes || echo no 		yes

test命令通常做判断, test 命令和 [ ] 等同
#前后必须有空格
[1 = 1] && echo yes || echo no 	 错误
[ 1 = 1 ] && echo yes || echo no 	正确

4.3 字符串测试

test "abc" == "bcd" && echo yes || echo no    判断字符串相等 注意 == 两边要有空格
test "abc" != "bcd" && echo yes || echo no    判断字符串不相同 

判断字符串不是null 
 test $abc  && echo yes || echo no    abc 存在 输出 yes 不存在输出 no
 判断字符串是null
 test -z $abc  && echo yes || echo no   abc不存在 输出yes 存在输出 no
 [ $abc ] && echo yes || echo no  不是空 yes  是空 no
 
 if(name !=null ){
   
 }

4.4 文件测试

-d 判断是否是文件夹
-f 判断是否是文件 
-L 判断是否是超链接 快捷方式
-e 判断是否存在
-r 判断是否有读权限
-w 判断是否有写权限 
-x 判断是否是执行权

test -d 1.txt && echo yes || echo no  
[ -d 1.txt ]  && echo yes || echo no  
[ -f 1.txt ]  && echo yes || echo no  
[ -e 1.txt ]  && echo yes || echo no  
[ -L /bin ] && echo yes || echo no  
[ -r 1.txt -a -w 1.txt ] && echo yes || echo no 
[ -x 1.txt ] && echo yes || echo no
 

4.5 if语句判断

单条件判断
if [ 条件 ]
 then 
 	执行
fi

互斥条件判断
if [ 条件 ]
then 
	程序
else 
	程序
fi

#!/bin/bash
read -p '请输入您的年龄:' AGE
if [ $AGE -ge 18 ]
  then
        echo "你成年了可以看片了"
  else
        echo "你还未成年 滚蛋"
fi

#判断传入的参数 $1是否存在 存在打印值 不存在 则输出不存在
#!/bin/bash
name=$1
if [ $name ]
    then
        echo "$name"
    else
        echo "name不存在"
fi

多条件判断
if [ 条件1 ]
  then 
  	  执行 
 elif [ 条件2 ]
  then 
  	 执行
 ...
 else 
 	执行	
fi

#!/bin/bash
if [ $1 -ge 90 -a $1 -le 100 ]
        then
             echo  "优秀"
elif [ $1 -ge 80 -a $1 -lt 90 ]
        then
              echo  "良好"
elif [ $1 -ge 60 -a $1 -lt 80 ]
        then
             echo  "及格"
elif [ $1 -ge 0 -a $1 -lt 60 ]
        then
              echo "潜力非常大"
else
        echo "分数有误"
fi

4.6 case选择语句

#!/bin/bash
read -p '请输入一个数字(1-7):' NUM
case  $NUM in
1 )
	echo "星期一"
	;;
2 ) 
	echo "星期二"
	;;
3 ) 
	echo "星期三"
	;;
4 ) 
	echo "星期四"
	;;
5 ) 
	echo "星期五"
	;;
6 ) 
	echo "星期六"
	;;
7 ) 
	echo "星期日"
	;;
* ) 
	echo "你瞎啊"
	;;
esac

5.循环

5.1 for循环

for (( 初始化表达式;布尔表达式;步进表达式 )) 
	do 
		程序 
	done
#!/bin/bash
for (( i=0 ;i<=100;i++ ))
	do 
		echo "$i"
	done
#!/bin/bash
sum=0
for(( i=0;i<=100;i++))
	do 
		sum=$[$sum+$i]
	done
echo $sum

for 变量 in  值1 值2 值3
do
	程序
done
或者写成一行 
for 变量 in 值1 值2 值3 ; do 程序 ; done

#!/bin/bash
for N in $*
do 
	echo $N
done

**for循环案例:**在每台机器的根目录下 创建一个当前日期的文件夹 如果文件夹已存在则删除 创建 如果不存在则创建

#!/bin/bash
for hostname in linux01 linux02 linux03   #linux0{1..3}   `cat workers`  
do 
	echo "连接$hostname"
	ssh $hostname  "if [ -e /`date +%Y-%m-%d` ]
					then
					  echo "先删除再创建"
                    	rm -rf /`date +%Y-%m-%d`
                    	mkdir /`date +%Y-%m-%d`
                      else
                      	echo "直接创建文件夹"
                      	 mkdir /`date +%Y-%m-%d`
                     fi; exit"
     echo "退出$hostname"
done


vi workders
linux01
linux02
linux03
猜数字小游戏
$RANDOM生成随机数  0-32767

#!/bin/bash
g=$[ $RANDOM%100+1 ]
for((;;))
do 
	read -p '请输入您要猜的数字' NUM
	if [ $NUM == $g ]
	then 
		echo '您猜对了'
		exit;
	else
		if [ $NUM -gt $g ]
		then 
			echo '您猜大了'
		else
			echo '您猜小了'
	    fi
	fi
done

5.2 while循环

while [ 条件判断式 ] 
  do 
程序
...
  done
#!/bin/bash
num=1
while [ $num -le $1 ]
do 
	echo "$num"
	#num=$[$num+1]
	let num++
	sleep 1  #睡眠1秒
done

6.数组

定义数组
	arr=(1 2 3 4 5 "abc");
为数组元素赋值
	arr[0]=100
	arr[1]=200
根据指定索引获取元素
${arr[索引]}
获取数组中所有元素
${arr[*]}
${arr[@]}
获取数组的长度
${#arr[*]}
${#arr[@]}

遍历数组 
for n in ${arr[*]}
do
	echo $n
done

写成一行 for n in ${arr[*]};do echo $n;done

将脚本的输入参数转成一个数组
#!/bin/bash
arr=($@)
for n in ${arr[*]}
do 
	echo $n
done

7.函数

7.1 系统函数

basename 命令会删掉所有的前缀包括最后一个(‘/’)字符,然后将字符串显示出来。
basename /mysh/for.sh  ---> for.sh
basename -s .sh /mysh/for.sh   ----->for  不显示后缀
basename /mysh   ---> mysh
basename -a  /aaa/b.txt /ccc/d.txt   -----> b.txt  d.txt  


dirname 从给定的包含绝对路径的文件名中去除文件名(非目录的部分),然后返回剩下的路径(目录的部分)
dirname  /mysh/a.txt   ---->/mysh
dirname /mysh/1.txt /aaa/b.txt  ----> /mysh /aaa

7.2 自定义函数

function 函数名(){
  
    函数体
   return 返回值
}

注意:
	function可以省略不写 
	()可以省略不写 但是函数名和{}之间要有空格
	return可以结束函数 
	return默认返回最后一个命令的状态,也可以给定参数值 范围在 0-255
	如果没有return 默认返回最后一个指令的退出状态值  $?
vi fn1.sh
#!/bin/bash
function hello(){
  	echo "hello"
  	echo "world"
}
调用方式 
	在当前shell脚本中调用
	hello
	在外界的bash中调用 
	source fn1.sh
	hello


function mymkdir(){
  	echo "正在创建文件夹$1"
  	mkdir $1;
}
调用
	mymkdir aaa
	
function mymkdir(){
  	echo "正在创建文件夹$1"
  	return  
  	echo "老子不创建了"
  	mkdir $1;
}
#方法遇到return就结束 后面不执行了

function mymkdir(){
  	 echo "正在创建文件夹$1"
  	 mkdir $1
  	 #return 10
}
外界调用 
   source fn1.sh
   mymkdir  aaa  
   创建成功 $? 返回 0 
   mymkdir 不传参数 创建失败 返回非0
   加了return 10之后  无论成功还是失败 都是10
请用户输入信息  如果不输入一直提示 输入后 打印用户输入的信息
#!/bin/bash
function  userinput(){
  	input_var=
  	output_var=$1
  	while [ -z $input_var ]
  		do 
  		   read -p "$output_var:" IN
  		   input_var=$IN
  		done
  	echo "$input_var"
}

userinput "请输入您的姓名"

8.定时任务

crontab -e
*  *  *  *  *    
分 时 日 月 周

分:每小时的第几分
时:每天的第几时 0-24
日:每月的几号
月:每年的哪月 
周:每周的第几天

* * * * *  代表每分钟

1 * * * *  每小时的01分执行

1 14 * * *  每天的14点01分执行

1 14 1 * *  每月1号的14点01分执行
1 14 2 7 *  每年7月2号的14点01分执行
1 14 * 7 2  每年7月的每周的第2天 14点01分执行

每周二至周五,下午6点  的计划任务
0   18   *    *    2-5  (2,3,4,5)
1到10月份,每周二周五,下午6点的计划任务
0     18       *   1-10  2,5
12点和14点,检查apache服务是否启动 每年的1-3月7-9月 周一到周5
0  12,14  *   1-3,7-9   1-5   

cat  /var/spool/cron/root  查看错误信息

9.高级文本编辑工具

9.1 cut

cut -d 指定切割方式 -f 第几列   文件名

vi cut.txt 
001 liuyan 38 nv
002 tangyan 18 nv
003 jinlian 138 nv
004 dalang 8 nan

cut -d " " -f 1 cut.txt  按照" "来切 显示第一列
001
002
003
004

cut -d " " -f 2,3 cut.txt 按照" "来切 显示2 3列
liuyan 38
tangyan 18
jinlian 138
dalang 8

#获取到柳岩的id
cat cut.txt | grep liuyan
001 liuyan 38 nv
cat cut.txt | grep liuyan | cut -d " " -f 1
001

echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/opt/apps/jdk1.8.0_191/bin:/root/bin
选取系统PATH变量值,第2个“:”开始后的所有路径:
echo $PATH | cut -d ":" -f 2-

ifconfig ens33 | grep "inet "| cut -d "i" -f 2-|cut -d " " -f2

9.2 sed

sed是一种流编辑器,它一次处理一行内容。处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”,接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。接着处理下一行,这样不断重复,直到文件末尾。文件内容并没有改变,除非你使用重定向存储输出

sed [选项参数]  ‘command’  filename

vi sed.txt 
001 liuyan 38 nv
002 tangyan 18 nv
003 jinlian 138 nv
004 dalang 8 nan

#显示的时候在第二行后插入 003 ximenqing 100 nan   a 新增,a的后面可以接字串,在下一行出现 
sed '2a 003 ximenqing 100 nan' sed.txt

#删除包含001的记录  d 删除
sed '/001/d' sed.txt 

查找替换 sed 's/要被取代的字串/新的字串/g'  文件名
#将所有00 替换成 ""
sed 's/nv/女/g' sed.txt
sed 's/0//g' sed.txt

# 删除第二行  并将所有00 替换成""  -e同时执行多个指令
sed -e '2d' -e 's/0//g' sed.txt

#显示时去除空行
sed '/^$/d' sed.txt 
#修改文件 -i 删除文件中所有空行
sed -i '/^$/d' sed.txt 

#给指定1-3行范围添加注释
sed -i '1,3s/^/#/g' sed.txt
#将所有的注释删除
sed -i 's/^#//g' sed.txt


#在001开头这一行下 加入 002
sed -i '/^001/a\002' sed.txt
#在001开头这一行 上面 加入 0000
sed -i '/^001/i\0000' sed.txt
每一行之间都必须要以反斜杠 \ 来进行新行标记
a :新增, a 的后面可以接字串,而这些字串会在新的一行出现(目前的下一行)
i :插入, i 的后面可以接字串,而这些字串会在新的一行出现(目前的上一行)

9.3 awk

一个强大的文本分析工具,把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行分析处理。

awk [选项参数] ‘pattern1{action1}  pattern2{action2}...’ filename
pattern:表示AWK在数据中查找的内容,就是匹配模式
action:在找到匹配内容时所执行的一系列命令

-F	指定输入文件折分隔符
-v	赋值一个用户定义变量

vi awk.txt
001 liuyan 38 nv
002 tangyan 18 nv
003 jinlian 138 nv
004 dalang 8 nan

#以空格进行切割 查找以001开头的所有行 打印第2列
awk -F " " '/^001/{print $2}' awk.txt
#以空格进行切割 查找以001开头的所有行 打印第2列 第3列 用,分隔
awk -F " " '/^001/{print $2 "," $3}' awk.txt
#在查找的内容之前打印 hello 在结尾打印 world
awk -F " " 'BEGIN{print "hello"}/^001/{print $2 "," $3}END{print "world"}' awk.txt

#给所有用户的年龄+10在输出
awk -F " " -v i=10 '{print $3+i}' awk.txt

内置变量
FILENAME	文件名
NR	已读的记录数 第几行 
NF	浏览记录的域的个数(切割后,列的个数) 切割的列数

awk -F " " '{print FILENAME,NR,NF}' awk.txt

#打印所有空行号
awk '/^$/{print NR}' awk.txt 

ip
ifconfig ens33 | grep "inet " |awk -F " " '{print "ip地址是:"$2}' 

9.4 sort

sort命令是在Linux里非常有用,它将文件进行排序,并将排序结果标准输出。

sort 参数  文件 
-n 以数值的方式排序  不指定以字符串形式排序 1 11 111 2 22
-r 逆序
-t 指定分隔符
-k 指定列

vi sort.txt
001 liuyan 38 nv
002 tangyan 18 nv
003 jinlian 138 nv
004 dalang 8 nan

sort -t " " -nk 3 sort.txt
sort -t " " -nrk 3 sort.txt
sort -t " " -nk 3 sort.txt >> 1.txt
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值