shell编程

本文概述了shell的基础概念,包括shell的作用、主要种类(如bash、sh和csh),shell脚本的建立与执行流程,以及shell变量的分类、替换、匹配与操作。还介绍了流程控制、循环语句、函数、数组和正则表达式的应用。
摘要由CSDN通过智能技术生成

shell介绍

一. shell解释

  1. shell:命令解释器,用户通过键盘输入给终端显示,终端交给shell去解释用户输入的命令,然后交给内核读取
  2. shell是解释执行用户输入的命令和程序,从键盘一输入命令就可立即得到回应的对话方式叫做交互的方式

  3. shell存在于Linux操作系统的最外层,中间是系统的核心内核,最里面一层就是硬件设备

  4.  shell负责与用户直接对话,把用户的输入解释给操作系统,并处理各种各样的操作系统的输入结果然后输出屏幕返回给用户。输入系统的用户名和密码并登录到Linux后的所有操作都是由shell解释执行!

 二.shell的种类

1. Bourne shell分为bourne shell(sh);Korn shell(ksh);(bash)
 sh:标准的UNIX Shell
ksh:是sh的超集合,目前很多unix系统标配的shell,/bin/sh是指向/bin/ksh的符号链接
bash:各种Linux发行版默认配置的shell,/bin/sh是指向/bin/bash的符号链接

2. C shell:csh tcsh
csh:支持很多sh所不支持的功能
tcsh:加入了命令补全等功能,在Mac OS上代替了csh
cat /etc/shells (其中默认的shell是/bin/bash;其中/bin/sh是指向/bin/bash)

1. 其他脚本语言 (PHP语言;Perl语言;Python语言)
2. 查看操作系统默认的SHELL (两种方法) 
    1. (echo $SHELL) --bash 
    2. 查看/etc/passwd底下的最后一列/bin/bash(用户登录后的shell解释器)

三.shell脚本的建立和执行

建立:
第一行#!/bin/bash (指定哪个程序(解释器)来执行脚本的内容)
以下出现的#都代表注释
其中!系统自带的软件启动脚本的第一行显示:/bin/bash

显示bash的版本:bash --version

[root@tttyyy-ty system]# bash --version
GNU bash, version 4.2.46(2)-release (x86_64-redhat-linux-gnu)

在Centos和RedHat Linux中默认的shell都为bash,因此在写shell脚本的时候脚本的开头不加默认就是bash解释,若不需该解释器则必须指定

例:     #!/usr/bin/env python python语言解释器 
         #!/usr/bin/perl         perl语言解释器
        #!/usr/bin/expect     expect解决交互式的语言开头解释器
执行
shell脚本运行时,先查找系统环境变量的env,该变量制定了环境文件(/etc/profile ---~/.bash_profile ---~/.bashrc----/etc/bashrc)
shell脚本执行的时候,会向系统内核请求启动一个新的流程,以便在该进程中执行脚本的命令和子shell脚本

1. bash/sh 脚本名  :当脚本文件本身没有可执行权限(开启子shell执行脚本)
2. path/脚本名;./脚本名 : 需要赋予执行权限
3. source/. 脚本名:在当前的父shell进程中执行(可在当前shell使用变量

[root@tttyyy-ty test]# cat >12.txt
   echo 13243
   [root@tttyyy-ty test]# cat 12.txt
   echo 13243
4. 通过source 和. 加载执行过的脚本,是在当前shell执行脚本,脚本中的变量和函数值都会在当前shell中依然存在,而sh和bash都会启动新的子shell执行,执行完之后退回到当前shell,其中变量值等都无法保留。
5. 在~/.vimrc配置文件配置vim编辑文件时自动加上一下注释信息的功能

shell变量

一.shell变量种类

可在创建它们的shell和任意子shell中使用,export定义
1. 自定义环境变量 
2. bash内置的环境变量
   $SHELL $HOME $PWD $USER $UID $PATH
=====================================================
1. 临时环境变量:在命令行中设置创建
2. 永久环境变量:在用户家目录.bash_profile 或.bashrc(非用户登录模式特有,远程SSH);或者全局配置/etc/bashrc 或/etc/profile定义 
   export BOY   ===>  source /etc/profile 
=========================================================
设置登陆后显示的内容有两种方式:
1. /etc/motd  
2. 可在/etc/profile.d/下面写一脚本
      内容为 '"echo "注意事项..."'  退出再连接即可生效
=========================================================
注:在写shell脚本可直接使用系统默认的环境变量,一般情况下是不需要重新定义的,在使用定时任务等执行shell脚本时建议在脚本中重新定义

环境变量初始化和对应文件的生效顺序

在登录Linux系统并启动一个bash shell时,默认情况下bash会在若干个文件中查找环境变量的设置,成为系统环境文件。bash检查的环境变量文件的情况取决于系统运行shell的方式,一般有三种
1)通过系统用户登录后默认运行的shell
2)非登录交互式运行shell
3)执行脚本运行非交互式shell

===========================================================
当用户登录Linux系统时,shell会作为登录shell启动,此时登录shell会加载环境变量的顺序为/etc/profile --> /etc/profile.d/脚本文件 --> $HOME/.bash_profile-->$HOME/.bashrc-->/etc/bashrc   有则执行无则不执行

若用户的shell不是登录时启动(手动敲下bash启动或其他不需要输入密码的登录和远程SSH连接的情况),那么非登录shell只会加载$HOME/.bashrc,并会去找/etc/bashrc(全局环境变量文件)

因此,如果希望在非登录shell下读到设置的环境变量内容,将变量写入$HOME/.bashrc或/etc/bashrc

1.用户自定义变量(普通变量)

①变量名=值
②将一个命令的执行结果交给变量:变量名=`命令`或者变量名=$(命令)

注!!环境变量和自定义变量的区别:
环境变量拥有可继承性,普通变量无继承性

当使用sh或bash运行脚本的话shell无法使用父shell的普通变量,若使用source和. 运行脚本的话子shell可调用父shell的普通变量

$变量名:输出变量 可写$C 或者${C}

当变量后面连接其他字符的时候,必须给变量加上大括号{},例如$Cname,其中C是个变量,若这样写则将误以为Cname为一个变量,所以表示为${C}nam

 单引号:所见即所得,将内容原样输出,俗称强引用

双引号(默认):会解析内容中的(有命令,变量,特殊转义符)的内容然后再输出最终结果,俗称弱引用

无引号:赋值时,若变量内容中有空格,则会造成赋值不完整,在输出内容时,会将含有空格的字符串作为一个整体输出;若内容中有命令(反引),变量,先把变量,命令解析除结果然后输出最终内容;若字符串中带有空格等特殊字符,有可能无法完整输出,因此需要改加双引号。

 2.位置变量

$0: 当前脚本名字 sh 12.sh (其中$0:当前脚本名字)

awk中的$0: 代表处理的整行内容

$0-$9:代表传参的位置参数变量

${10}:需加大括号

$#:位置参数的个数

$@:所有位置参数的内容,单个输出

$*:所有位置参数的内容,整体输出

$*和$@的区别:
注:在未加双引号的情况下两者无区别
在加了双引号的情况下"$*" :是作为一个字符串输出;"$@":是单个输出字符串

 3.预定义变量

1. $?: 最后一次执行命令的返回状态,若变量为0则证明上一条命令执行成功,若非0则不成功 (其中逻辑符号&&就是根据返回值判断是否为真)

2. $$:当前进程的进程号 当前bash的进程号
   若用bash和sh运行脚本的时候则显示当前脚本执行生成的pid号
   若用source 和. 运行脚本的话则显示当前bash进程的pid号

3. $!: 后台运行的最后一个进程的进程号

4.环境变量

环境变量 :命令在环境变量里面的路径就可直接执行
shell在开始执行时已经定义好的 
		env 查看所有环境变量
		set 查看所有变量 
				环境变量拥有可继承性:export之后就拥有继承性
				(普通变量无继承性)
		当使用sh运行的话子shell是无法使用父shell普通变量;若使用source运行脚本的话子shell可以调用父shell的普通变量
		export 导出变量(作用范围) 
临时生效:命令行上执行

永久生效
		写到4个登陆脚本中 ~/.bashrc ~/profile 更好放在/etc/profile.d/* 下建立独立的环境变量配置文件
		常用环境变量:USER UID HOME HOSTNAME PWD PS1 PATH
PATH:存储所有命令所在的路径
hostname -I:获取网卡的IP地址

 查看和取消变量

1. env (全局变量)
2. set (自定义变量和环境变量)set -o(显示bash shell的所有参数配置信息)
3. declare (输出所有的变量,函数,整数和已经导出的变量)

取消变量
   unset 变量名 仅在当前shell中有效 (可取消环境变量)

 二.shell变量替换

1. ${par:-word}:若变量为空或未设置,则用后面的值代替,但变量值不变;若不为空则不替换
2.${par:=word}:若变量为空或未设置,则用后面的值代替,变量值改变
3.${par:+word}:若变量不为空则用后面的值代替,变量值不变(若变量无内容则不进行替换)---多用于错误输入变量值的时候使用
4.${par:?word}:若变量为空或者未设置,则word作为标准错误输出打印出来(可检查变量是否正确)
 e.x.p.
echo ${a:?unset a}  
-bash: a: unset a
echo $? :1 返回值不为0,则表示上条命令返回值

三. shell变量匹配截取

${变量#关键词}  若变量内容从头开始的数据符合『关键词』,则将符合的最短数据切除
${变量##关键词} 若变量内容从头开始的数据符合『关键词』,则将符合的最长数据切除
${变量%关键词}  若变量内容从尾向前的数据符合『关键词』,则将符合的最短数据切除
${变量%%关键词} 若变量内容从尾向前的数据符合『关键词』,则将符合的最长数据切除
${变量/旧字符串/新字符串} 若变量内容符合『旧字符串』则『第一个旧字符串会被新字符串替代』
${变量//旧字符串/新字符串} 若变量内容符合『旧字符串』则『全部的旧字符串会被新字符串替代』

四.shell变量切片

a=12345678
echo ${a:5} //从第5位开始截取 0最小(包括第五位)
678
echo ${a:3:4}  //从第三位开始取思维长度,后面整数代表截取的长度
4567
echo ${a:2:-1}  匹配到最后一位之前(不包括最后一位)
34567
echo ${a:2:-2}  匹配到倒数第二位之前
3456
url=www.sina.com.cn 
echo ${#url} //获取变量的长度 
15
=====================================================================================
basename 命令 路径中的文件名
dirname  命令  文件的路径,去除文件名,打印文件目录
例:dirname获取当前脚本的路径
pwd=$( cd $(dirname $0);pwd)
if [ $path == '/opt' ];then
    echo "路径执行正常"
else
    echo "请将脚本放置在/opt下执行"
    exit 3
fi

shell流程控制

test 条件 (为真返回0,为假返回1)
等同于 [ 条件 ]
1. 字符比较
-n str : 有字符长度 则返回0,无则返回1
-z str : 字符串长度为0 为0返回0,不为空返回1
== = :判断两个字符串是否一样 
!= :判断两字符串是否不一样
2. 数字比较
eq 等于 =    
ne(不等于)
ge 大于等于   
le(小于等于)
gt 大于       
lt(小于)
3. 文件判断
-e  不论类型,该文件是否存在
-f   文本文件是否存在
-d   目录文件是否存在
-h    存在且是符号链接
-b    块设备
-c    字符设备
==============================================================
1. if语句(执行真还是假)
if [ 表达式 ];then    
条件成立执行
elif [ 表达式2 ];then    
表达式2成立执行
else    
所有条件不成立执行
fi
其中if [ >90](>90) elif [>60](60-90) else(<=60)
多个条件联合
逻辑与
if [ $condition1 ] && [ $condition2 ] 
if [ $condition -a $condition2 ]
if [[ $condition1 && $condition2 ]]   报错情况少,更加稳定,推荐使用
逻辑或
if [ $condition1 ] || [ $condition2 ] 
if [ $condition -o $condition2 ]
if [[ $condition1 || $condition2 ]]
# test 和 [] 中 我们可以使用 [ $condition1 ] && [ $condition2 ] 或者 [ $condition -a $condition2 ]​
# 在 [[]] 这种情况,我们可以直接使用[[ $condition1 && $condition2 ]]建议在if中直接使用[[]]这种方式,这种方式更加稳定。
[[]] shell的一个命令。
-a &&  逻辑与 and 两端的条件都可以成立
-o ||  逻辑或 or  两端的条件有一段成立就行
2.case语句
case $var in
模式1)                
      执行1                
      ;;
模式2)                
      执行2                
      ;;
模式3)                
      执行3                
      ;;
*)                
      执行4
esac

shell循环语句

1.for语句
for i in 范围 (for识别空格和换行)
do   
  循环体
done
测试生产环境的主机存活性
{
}&并发(不按顺序)
cat <<EOF
内容
EOF
for i in `cat /etc/passwd`
do    
    循环体
done
2. while语句
while 条件    # while 关键字 条件  [ $1 -lt 10 ] ,while循环,条件为真的情况下,会循环
do            #条件可为 2>1 或 :   
    循环体
done
while read line   
do   
    循环体
done< /etc/passwd   #读取文件的每一行交给line变量处理;i++:默认i=0开始=================================================================
循环控制(shift,continue,break,exit)
exit(直接退出脚本,可以返回一个返回值) 
break(直接跳出循环,还会执行下面的语句)
countine(跳出本次循环,在continue后面的语句不执行,但是后面的循环还是会执行)
shift (将位置参数左移)

shell函数

函数定义
function func(){  
    函数体
}
函数名(){    
    echo $1    
    函数体
}
函数调用 # 直接写函数名字
func 'name'  # 函数名 name 为函数位置参数 $1

​func(){    
    local a    
    a=10
}
func
echo $a
# 使用local声明过的变量,拥有了属于自己的名称空间,不会被函数外部使用​
func(){    
    return 10
}
func
# 类似于exit 后的数字,是函数执行之后返回的返回值,限制为数字不大于255取消函数 unset 函数名函数传参 
在Shell中,调用函数时可以向其传递参数。在函数体内部,通过 $n 的形式来获取参数的值,例如,$1表示第一个参数,$2表示第二个参数 

shell数组

#将不同的数据类型变为一个类型数组
!!!直接打印则是打印第一个元素
#都是从0开始(计算机中)
普通数组:只能用整数作为数组的索引(下标只能为数字)
关联数组:可以使用字符串作为数组的索引
#关联数组需要提前声明 (给数组的每个元素关联一个名字)
declare -A myarry1
#普通数组定义
--- declare -a myarry=(5 6 7 8) 默认为普通数组,可不声明a
--- echo ${myarry[2]}
不要加逗号不要加逗号!!!
#访问数组
[root@newrain shell]# aa=(haha heihei baibai)
[root@newrain shell]# echo ${aa[0]}    //访问数组中的第一个元素
[root@newrain shell]# echo ${aa[@]} 		//访问数组中所有的元素,等同与echo ${aa[*]}
[root@newrain shell]# echo ${#aa[@]}   //统计元素的个数
[root@newrain shell]# echo ${!aa[@]}   //统计索引
echo ${#aa[2]}:打印元素的字符长度
##########################
# shell数组中"*" 和 "@" 区别 
关于在shell脚本中数组变量中 “*”跟 “@” 区别
“*”当变量加上“” 会当成一串字符串处理. 
“@”变量加上“” 依然当做数组处理. 
在没有加上“” 的情况下 效果是等效的.
遍历数组
#while 和 for 都可读取一个文件的内容
while只能一行一行识别
for空格和换行都可识别
[root@newrain array]# cat array01.sh 
#!/bin/bash#++ i 是先自加1后赋值;i ++ 是先赋值后自加1。 
while read line
do             
host[i++]=$line  # 观察i++ 和 ++i的区别 默认i=0
done </etc/hosts
for i in ${!host[@]}   # 数组的元素索引do        
	echo "$i:${host[i]}"
done
#遍历数组for!!!!!!!!!!!!!!
[root@newrain array]# cat array02.sh 
#!/bin/bash
IFS=''
for line in `cat /etc/hosts`  # 读取文件中的每一行do        
host[j++]=$linedone
for i in ${!host[@]}
do        
	echo ${host[i]}
done 
#作:统计shell的种类和数量
思路:最后一列的sh种类不同,我们可以单独取出最后一列 /etc/passwd
while read aaa
        do
        type=`echo $aaa | awk -F ":"  '{print $7}'`
        shell[$type]=$[${shell[$type]}+1]
done < /etc/passwd
     #echo ${shell[@]}
for i in ${!shell[*]}
do
       echo "$i:${shell[$i]}"
done

正则表达式

1.正则:在计算机之前发明的,用来研究医学类
2.正则表达式:检索信息,找到我们查找的内容 
---处理文件内容
#通配符号(*,{}):匹配文件名 ; 正则匹配文件内容
#正则表达式基本元字符
1.^ :以什么信息开头
grep "^root" /etc/passwd  #匹配以root开头的行
2.$ :以什么信息结尾grep "nologin$" /etc/passwd #匹配以nologin结尾的行 
#正则表达式拓展元字符(^$:空行)
3. . : 匹配单个字符
4. * : 匹配前导符0到多次
.*                      匹配任意多个字符  (贪婪匹配  有多少最大匹配多少grep贪婪一行
.*?  非贪婪匹配(只要匹配了就结束!)  
?(属于扩展正则需要加E)
[]                      匹配方括号中任意一个字符
[lL]ove
[ - ]                   匹配指定范围内的一个字符[a-z0-9]ove  
[^]                     匹配不在指定组里的字符[^a-z0-9]ove 
\                       用来转义元字符
love\.                  
\<                      词首定位符 #由数组或字母组成的
\<love                             在一个单词中的不会被匹配!!!!​
\>                      词尾定位符
love\>
#正则表达式拓展元字符
= 等于 != 不等于  =~  匹配
扩展正则表达式元字符
+                       前导字符匹配一个或多个
[a-z]+ove•?                       前导字符匹配零个或一个lo?ve
•a|b                     匹配a或blove|hate

•()                      组字符loveable|rs
love(able|rs) ov+ ov+ (ov)+ 
•(..)(..)\1\2            标签匹配字符  (love)able\1er
•x{m}                    字符x重复m次o{5}
•x{m,}                   字符x重复至少m次o{5,}
•x{m,n}                  字符x重复m到n次
#which [ :是个命令可以查看做判断
[root@newrain ~]# num1=1 
#运用正则,判断需要[[ ]] 
[root@newrain ~][[ $num1 =~ ^[0-9]+$ ]] && echo "yes" || echo "no"yes
[root@newrain ~] num3=1b1 
[root@newrain ~] [[ $num3 =~ ^[0-9]+$ ]] && echo "yes" || echo "no"    
#####只能以数字,字母不匹配no
[root@newrain ~] [[ $num =~ ^[0-9]+\.[0-9]+$ || $num =~ ^[0-9]+$ ]] && echo "yes" || echo "no"       //输入的只能是数字(包括小数)
# \< 词首定位符号 \>词尾定位符号 
[root@newrain ~]# cat jack.txt 
Jack JACK JAck jackly
% s/\<[Jj]ack\>/123/g
# \(\)匹配后的标签
[root@newrain ~]# cat file1.txt 
IPADDR=192.168.1.123 
GATEWAY=192.168.1.1 
NETMASK=255.255.255.0 
DNS=114.114.114.114
:% s#\(192.168.1.\)123#\12#
:% s#\(192.\)\(168.\)\(1.\)2#\1\2\35#
:% s\(192.\)\(168.\)\(1.\)\(5\)#\1\26.\4#
#补:跳板机:登录shell改为脚本路径就可连接以脚本执行
trap:信号捕捉,trap “echo 禁止操作” INT (ctr+c ctrl+d)

目录

shell介绍

一. shell解释

 二.shell的种类

三.shell脚本的建立和执行

shell变量

一.shell变量种类

 二.shell变量替换

三. shell变量匹配截取

四.shell变量切片

shell流程控制

shell循环语句

shell函数

shell数组

正则表达式


通过查看文档和自己的测试,bashdb-4.2.0-7 和centos7的bash-4.2.46版本匹配,并且编译顺利. 使用方法: 解压bashdb [root]#tar xf bashdb-4.2-0.7.tar.gz -C /usr/src 编译安装bashdb 编译安装bashdb有两种方法,区别可以看bashdb的帮助信息. 第一种编译方法: 不结合bash源代码编译和安装bashdb [root]#cd /usr/src [root]#cd bashdb-4.2.0-7 [root]#touch $HOME/missing [root]#touch libtoolT [root]#./configure --prefix=$HOME [root]#make [root]#make install 第二种编译方法: 结合bash源代码编译和安装bashdb 需要准备bash源代码 a).下载bash-4.2.46的src.rpm bash-4.2.46-20.el7_2.src.rpm http://vault.centos.org/7.3.1611/os/Source/SPackages/ b). 提取bash-4.2.46-20源代码 [root]#rpm -ivh bash-4.2.46-20.el7_2.src.rpm [root]#cd $HOME/rpmbuild/SPECS [root]#rpmbuild -bp bash.spec 此时,源代码已经安装到了$HOME/rpmbuild/BUILD目录 c).移动bash的源代码到/usr/src [root]#cd $HOME/rpmbuild/BUILD [root]#mv bash-4.2 bash-4.2.46-20 [root]#mv bash-4.2.46-20 /usr/src d). 准备bash的源码环境 [root]#cd /usr/src [root]#cd bash-4.2.46-20 [root]#./configure && make e). 结合bash编译安装bashdb [root]#cd /usr/src [root]#cd bashdb-4.2.0-7 [root]#touch $HOME/missing [root]#touch libtoolT [root]#./configure --prefix=$HOME --with-bash-src=/usr/src/bash-4.2.46-20 [root]#make [root]#make install 3. 配置bashdb [root]#vi ~/.bash_profile 在最后添加 MANPATH=$HOME/share/man:$MANPATH export MANPATH INFOPATH=$HOME/share/info export INFOPATH [root]#. ~/.bash_profile 设置inc文件路径.[重要.] [root]#mkdir /usr/share/bashdb/ [root]#ln -s ~/share/bashdb/bashdb-main.inc /usr/share/bashdb/ 4.使用bashdb [root]#bash --debugger yourscript.sh var1 var2
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值