Shell 编程基础

一、Shell入门基础

1.Shell 脚本的执行

​ (1)以相对路径的方式:

[root@wan day1]#vim +  haha.sh
[root@wan day1]#chmod +x  haha.sh
[root@wan day1]#./haha.sh

​ (2)以绝对路径的方式执行:

[root@wan ~]# /shell/day1/haha.sh

注:以上两种方法执行时,该脚本必须拥有可执行的权限,否则会出现报错

​ (3)指定解释器执行脚本

[root@wan ~]# sh /shell/day1/haha.sh 
[root@wan ~]# bash /shell/day1/haha.sh 
[root@wan day1]# sh haha.sh 
[root@wan day1]# bash haha.sh

​ (4)在当前shell环境中执行:

[root@wan day1]# source /shell/day1/haha.sh
[root@wan day1]# . /shell/day1/haha.sh 
[root@wan day1]# source haha.sh 
[root@wan day1]# . haha.sh 

注:前三种执行,会开启子shell执行脚本,最后一种,会在当前shell中执行脚本(会改变当前用户的所在目录)

2.echo 的使用

​ (1)标准输出:

[root@wan day1]# echo hello

​ (2)输出并不换行:

[root@wan day1]# echo -n hello

​ (3)输出启用反写线转义:

[root@wan ~]# echo -e "name:\twan"
(4)输出带颜色的内容:

格式:

echo -e "\033 [字体控制选项;字背景颜色;文字颜色m字符串1033 [0m"
常见的字体颜色:重置=0, 黑色=30,红色=31,绿色=32,黄色=33,蓝色=34,紫色=35,天蓝色=36,白色=37。
常见的背景颜色:重置=0, 黑色=40,红色=41, 绿色=42,黄色=43,蓝色=44, 紫色=45,天蓝色=46,白色=47。
字体控制选项: 1表示高亮,4表示下划线,5表示闪烁等。

例如:

[root@wan ~]# echo -e "\033[4;41;36m something here \033[0m" 

​ (5)显示变量内容:

echo $变量名
[root@wan ~]# echo $USER

​ (6)引用一个命令执行的结果:

[root@wan ~]# echo `whoami`
[root@wan ~]# echo $(whoami)

实例:编写一个脚本,显示当前系统时间、当前系统用户:

 echo "当前系统时间是:$(date +'%F %T')"
 echo "当前用户:$(whoami)"
3.printf 的使用
[root@wan day1]# printf "%s\n" $USER
[root@wan day1]# printf "%i\n" 266
[root@wan day1]# printf "%2.3f\n" 3.141592
4.history 的使用
history -w  //将历史命令写入缓存文件  .bash_history
[root@wan ~]# history -c      //清除历史命令
5.输入与输出重定向

(1)输入重定向: <

​ 1)输出结果作为标准输入:

[root@wan ~]# wc -l < /etc/passwd

​ 2)从文件输入内容:

cat < /etc/passwd

示例:快速生成文件:

# cat > user.lst << EOF
> tom
> bob
> john
> EOF

(2)输出重定向: >

​ 1)标准输出重定向:

[root@wan ~]# help > 1.txt   //以覆盖的方式将正确命令输出到指定文件
[root@wan ~]# cd  >> 1.txt	 //以追加的方式将正确命令输出到指定文件

​ 2)标准错误输出重定向:

[root@wan ~]# ipconfig 2> 2.txt   //以覆盖的方式将错误命令输出到指定文件
[root@wan ~]# ipconfig 2>> 2.txt  //以追加的方式将错误命令输出到指定文件

​ 3)将正确和错误的追加输出到同一文件

[root@wan ~]# (ls;lllls) >  3.txt  2>&1   //以覆盖的方式将错误和正确的命令输出到同一文件
[root@wan ~]# (mv;pwc) >  3.txt  2>&1   //以追加的方式将错误和正确的命令输出到同一文件
[root@wan ~]# (ifconfig;dydy) &> 5.txt   //以覆盖的方式将错误和正确命令输出到指定文件
[root@wan ~]# (ifconfig:dydy) &>> 5.txt  //以追加的方式将错误和正确命令输出到指定文件

​ 4)将正确和错误的追加输出到不同文件

[root@wan ~]# (ls;vy) >> 6.txt 2>>7.txt  //以追加的方式将错误和正确命令输出到不同文件
6.命令执行顺序

​ (1)按命令顺序依次执行: ;

[root@wan ~]# date;ls;lalalala;pwd

​ (2)若前面的命令没有执行成功,则不执行后面的命令 : &&

[root@wan ~]# date && ls && lalalala &&pwd

​ (3)前面执行成功后面不执行,否则反之: ||

[root@wan ~]# ls || pwd
[root@wan ~]# lslsls | pwd
7.管道符的使用:

​ 提取系统网卡的IP地址:

[root@wan ~]# ip a | grep ens33 | grep inet | cut -d /  -f1 | tr -s ' ' | cut -d' ' -f3

注:tr -s :讲多个空格压缩为一个空格

备份文件

cp  /etc/httpd/conf/httpd.conf{,http_bak}

二、变量

1.变量的命名

​ 变量命名使用数字、字母、下划线,且数字不能打头;尽可能见名知意

2.变量的定义

​ 变量名=变量值

​ 注:“=“ 两边不能有空格;定义字符串类型,字符串中间有空格,需要给字符加上引号

my_name=zhangsan
sge=18
Hobby="paly pingpong、badminton"
home_address="xi`an"
3.变量的分类和引用
(1)自定义变量:

​ 定义:

​ 变量名=变量值

​ 引用:

变 量 名 、 变量名、 {变量名}

​ 查看环境变量:

​ set

​ 取消变量:

​ unset 变量名

​ unset -v 取消变量

​ unset -f 取消函数

注:unset–默认取消变量,当参数不是变量时,才取消函数;

​ 且不能取消只读变量

user_name=wan           //定义变量
$user_name              //引用变量
$user_name              //引用变量
set                     //查看变量
set | grep ^user_name   //查看变量
unset user_name         //取消变量

​ 注:只读变量仅在当前shell生效,子shell不生效

(2)只读变量:

​ 特点:变量值不能被修改,且不能取消

​ 定义:

​ readonly 变量名=变量值

​ eclare -r 变量名=变量值

​ 查看:

​ readonly

[root@wan ~]# readonly my_name=zhangshuaige
[root@wan ~]# declare -r my_age=18
[root@wan ~]# readonly

注:用户自定义的只读变量,在系统重启后自动取消

(3)环境变量:

​ 定义环境变量

[root@wan ~]# dev_backup=/dev/sda1
[root@wan ~]# export dev_backup               //方法一
[root@wan ~]# export back_httpd=/etc/http/    //方法二

​ 查看环境变量:

[root@wan ~]# env | grep dev_backup    
[root@wan ~]# env | grep back_httpd
[root@wan ~]# printenv | grep back_httpd
[root@wan ~]# printenv | grep dev_backup

​ 注:这种定义方法(命令行定义)进在当前shell和当前shell的子shell中有效;

​ 让环境变量的修改在退出shell再次登录时仍有效,需要在相关配置文件中修改;

​ Bash的初始化文件有:/etc/profile、/.bash_profile、/.bash_login、/.profile、/.bashrc、/etc/bashrc

在这里插入图片描述

​ 区别: bash_profile只在会话开始的时候读取一次,而bashrc则每次打开终端时都会读取

1)配置文件的执行顺序
/etc/profile-->/etc/profile.d/*.sh-->~/.bash_profile-->/etc/bashrc-->~./.bashrc
2)登录式shell的配置文件执行顺序
(清除所有变量,通过文件重新读入)
a.直接通过终端输入账号密码登录
b.使用“su -UserName”切换的用户
执行顺序:(影响该shell的配置文件)
/etc/profile-->/etc/profile.d/*.sh-->~/.bash_profile-->~./.bashrc-->/etc/bashrc
3)非登录式shell配置文件执行顺序
(会继承上一个shell的全部变量):
 a.su UserName
 b.图形界面下打开终端
 c.执行脚本(进入子shell)
 d.任何其他的bash实例
执行顺序:(影响该shell的配置文件)
~./.bashrc-->/etc/bashrc-->/etc/profile.d/*.sh

注:让环境变量的修改在退出shell再次登录时仍有效,需要在相关配置文件中修改

​ /etc/profile /etc/profile.d

(4)位置变量:
[root@wan day2]# vim ex1.sh
echo "姓名:$1"
echo "年龄:$2"
echo "性别:$3"
[root@wan day2]# chmod +x  ex1.sh 
[root@wan day2]# ./ex1.sh 
姓名:
年龄:
性别:
E-mail:
[root@wan day2]# ./ex1.sh  张帅哥 18 男 123@321.com
姓名:张帅哥
年龄:18
性别:男
E-mail:123@321.com
(5)预定义变量:
$0 脚本名
$* 所有的参数
$@ 所有的参数
$# 参数的个数
$$ 当前进程的PID
$! 上一个后台进程的PID
$? 上一个命令的返回值 0表示成功

示例:

[root@wan day2]# vim ex1.sh
echo "姓名:$1"
echo "年龄:$2"
echo "性别:$3"
echo "E-mail:$4"
echo "------------------------------->"
echo "脚本名:$0"
echo "脚本个数:$#"
echo "脚本参数:$*"
echo "脚本参数:$@"
echo "上一个命令执行成功与否:$?"

[root@wan day2]# ./ex1.sh {2..10}
姓名:2
年龄:3
性别:4
E-mail:5
------------------------------->
脚本名:./ex1.sh
脚本个数:9
脚本参数:2 3 4 5 6 7 8 9 10
脚本参数:2 3 4 5 6 7 8 9 10
上一个命令执行成功与否:0

区分点:$* 、 $@ 的区别:

# set -- "I am" test command
[root@localhost Scripts]# for i in "$*";do echo $i;done
I am test command
[root@localhost Scripts]# for i in "$@";do echo $i;done
I am
test
command
[root@localhost Scripts]# for i;do echo $i;done
I am
test
command

注:$@ 和默认不写 执行效果一样

Tip:

​ 常见命令错误码:

​ 1>命令没发现 127

​ 2>没有文件或目录 2

​ 3>变量定义错误 127

​ 4>语法错误 2

4.变量的赋值
(1)直接赋值(显式赋值)

​ 变量名=变量值

user_name="zhang san"
(2)使用 read 从键盘读入
[root@wan day2]# read num
10
[root@wan day2]# echo $num
10
[root@wan day2]# read
20
[root@wan day2]# echo $REPLY
20
[root@wan day2]# vim +  ex2.sh
echo -n "请输入管理员用户名:"
read admin_user
echo "---------------->"
read -p "请输入普通用户的用户名:"  user_name
echo $admin_user
echo $user_name

[root@wan day2]# chmod +x ex2.sh 
[root@wan day2]# ./ex2.sh 
请输入管理员用户名:root
---------------->
请输入普通用户的用户名:wan
root
wan
(3)使用read命令:
[root@wan day2]# read -p "请输入该用户的密码:"  passwd
请输入该用户的密码:123
[root@wan day2]# echo $passwd 
123
(4)使用位置变量或者环境变量:
[root@wan day2]# vim ex3.sh  +
name=$1
user_name=$USER
echo $name
echo $user_name
[root@wan day2]# chmod +x  ./ex3.sh
[root@wan day2]# ./ex3.sh  wan
wan
root
(5)使用命令的输出
[root@wan day2]# fun=`ls /root/`
[root@wan day2]# echo $fun
[root@wan day2]# fun=$(ls /root/)
[root@wan day2]# echo $fun
(5)从文件读取
[root@system1 day2]# cut -d: -f1 /etc/passwd > user.lst
# for循环
for user in `cat user.lst`
do
	echo $user
done
				
# 或使用while循环
while read user
do
	echo $user
done < user.lst
5.引号的使用

“” ‘’ ``

单引号(' ')单引号括起来的字符都作为普通字符出现
双引号(" ")双引号括起来的字符,除“$”、“\”、“'”和“"”这几个字符仍是特殊字符并保留其特殊功能
外,其余字符仍作为普通字符对待,
反引号(``)。反引号括起来的字串被Shell解释为命令,在执行时,Shell首先执行该命令,并以它的
标准输出结果取代整个反引号(包括两个反引号)部分
[root@wan day2]# echo "系统登录用户:$USER"
系统登录用户:root
[root@wan day2]# echo '系统登录用户:$USER'
系统登录用户:$USER
[root@wan day2]# echo `ls -lh  /etc/httpd/conf.d/`
total 16K -rw-r--r--. 1 root root 2.9K Apr 2 21:13 autoindex.conf -rw-r--r--. 1 root root 366 Apr 2 21:14 README -rw-r--r--. 1 root root 1.3K Nov 27 2019 userdir.conf -rw-r--r--. 1 root root 824 Nov 27 2019 welcome.conf

注:引号的嵌套使用,必须单双引号错开使用

6.变量的作用域
(1)全局变量:

​ 全局变量可以在脚本中定义,也可以在某个函数中定义。在脚本中定义的变量都是全局变量,其作
​ 用域为从被定义的地方开始,一直到Shell脚本结束或者被显式地删除

​ 函数体外定义全局变量

#!/bin/bash
#定义函数
func()
{
#输出变量x的值
echo "$v1"
#修改变量x的值
v1=200
} #
在脚本中定义变量x
v1=100
#调用函数
func
#输出变量x的值
echo "$v1"

​ 函数体内定义全局变量

#!/bin/bash
#定义函数
func()
{
#使用local关键字定义局部变量
local v2=200
} #
调用函数
func
#输出变量的值
echo "$v2"
(2)局部变量:

​ 与全局变量相比,局部变量的使用范围较小,通常仅限于某个程序段访问,例如函数内部 ;

​ 在Shell语言中,可以在函数内部通过local关键字定义局部变量 ;

​ 函数的参数也是局部变量

#!/bin/bash
#定义函数
func()
{
#输出全局变量v1的值
echo "global variable v1 is $v1"
#定义局部变量v1
local v1=2
#输出局部变量v1的值
echo "local variable v1 is $v1"
} #
定义全局变量v1
v1=1
#调用函数
func
#输出全局变量v1的值
echo "global variable v1 is $v1"
6.变量的运算:
[root@wan day2]# echo $((3+8*99/9))
91
[root@wan day2]# echo $[3+8*99/9]
91
[root@wan day2]# let num=3+8*99/9
[root@wan day2]# echo $num
91
[root@wan day2]# echo 3+8*99/9 | bc
91     
[root@wan day2]# expr 3 + 5 / 4               //运算符前后必须有空格 
4                                                                   
[root@wan day2]# declare -i num=2+5
[root@wan day2]# echo $num
7
[root@wan day2]# awk ' BEGIN {print 3+4*5/6}'
6.33333

6.字符串的处理:

[root@localhost ~]# str1="hello world"
[root@localhost ~]# echo ${#str1}
11
变量截取
指定起始位置,一直到结束
[root@localhost ~]# echo ${str1:1}
ello world
指定长度,不指定起始位置默认从开头开始
[root@localhost ~]# echo ${str1::3}
hel
指定起始位置和长度
[root@localhost ~]# echo ${str1:1:3}
ell
从右边第几个字符开始,及字符的个数
[root@localhost ~]# echo ${str1:0-1:1}
d 输
出右边的几个字符
[root@localhost ~]# echo ${str1:0-5}
world
[root@localhost ~]# echo ${str1: -5}
world
注意:下面写法会输出全部,以${parameter:-default}方式,默认是提取完整地字符串
[root@localhost ~]# echo ${str1:-5}
hello world
删除字符串:
// 获取后缀名tar.gz
[root@localhost ~]# filename=testfile.tar.gz
[root@localhost ~]# file=${filename#*.}
[root@localhost ~]# echo $file
tar.gz
// 获取后缀名gz
[root@localhost ~]# filename=testfile.tar.gz
[root@localhost ~]# file=${filename##*.}
[root@localhost ~]# echo $file
gz
//截取testfile.tar
[root@localhost ~]# filename=testfile.tar.gz
[root@localhost ~]# file=${filename%.*}
[root@localhost ~]# echo $file
testfile.tar
//截取testfile
[root@localhost ~]# filename=testfile.tar.gz
[root@localhost ~]# file=${filename%%.*}
[root@localhost ~]# echo $file
testfile
[root@wan day2]# dirname /usr/local/bin/            //取出文件所在目录
/usr/local
[root@wan day2]# basename /usr/local/bin/		 	//取出该路径下的文件
bin
[root@wan day2]# 

​ 字符串变量的替换:

[root@wan day2]# words="this is a boy"
[root@wan day2]# echo $words
this is a boy
[root@wan day2]# echo ${words/boy/girl}
this is a girl
[root@wan day2]# echo ${words//is/IS}
thIS IS a boy
7.shell 变量扩展配置

示例:

-示例:用法1,如果parameter变量值为空或未赋值,则返回word字符串代替变量的值
//变量未赋值,输出为空。
[root@localhost ~]# echo $var1
[root@localhost ~]# var2=${var1:-hello}
[root@localhost ~]# echo $var2
hello
-示例:用法2,如果parameter变量值有值,则变量返回parameter变量的值
[root@localhost ~]# var1="hello"
[root@localhost ~]# echo $var1
hello
[root@localhost ~]# var2=${var1:-world}
[root@localhost ~]# echo $var2
hello
=示例:用法1,如果parameter变量值为空或未赋值,则返回word字符串代替变量的值
注意和-,不同点在于var1没有赋值,将word赋值刚给var1
[root@localhost ~]# unset var1 var2
[root@localhost ~]# var2=${var1:=world}
[root@localhost ~]# echo $var2
world
[root@localhost ~]# echo $var1
world
=示例:用法2,如果parameter变量值有值,则返回parameter变量的值
[root@localhost ~]# unset var1 var2
[root@localhost ~]# var1=hello
[root@localhost ~]# var2=${var1:=world}
[root@localhost ~]# echo $var2
hello
[root@localhost ~]# echo $var1
hello
?示例:
{parameter:?word}的作用是: 如果 parameter 变量值为空或未赋值, 那么 word 字符
串将被作为标准错误输出, 否则输出变量的值。
[root@localhost ~]# unset var1 var2
[root@localhost ~]# var2=${var1:?world}
-bash: var1: world
[root@localhost ~]# unset var1 var2
[root@localhost ~]# var1=hello
[root@localhost ~]# var2=${var1:?world}
[root@localhost ~]# echo $var2
hello
[root@localhost ~]# echo $var1
hello
+示例:
${parameter:+word}的作用是: 如果 parameter 变量值为空或未赋值, 则什么都不
做, 否则 word 字符串将替代变量的值
[root@localhost ~]# unset var1 var2
[root@localhost ~]# var2=${var1:+world}
[root@localhost ~]# echo $var2
[root@localhost ~]# unset var1 var2
[root@localhost ~]# var1=hello
[root@localhost ~]# var2=${var1:+world}
[root@localhost ~]# echo $var2
world
[root@localhost ~]# echo $var1
hello

三、Shell 条件测试

1.条件测试基本语法

​ 在Shell程序中,用户可以使用测试语句来测试指定的条件表达式的条件的真或者假。当指定的条件

​ 为真时,整个条件测试的返回值为0;反之,如果指定的条件为假,则条件测试语句的返回值为非0值

​ 格式1: test 条件表达式

​ 格式2: [ 条件表达式 ]

​ 格式3: [[ 条件表达式 ]]

2.文件测试

在这里插入图片描述

//普通文件测试
[root@localhost ~]# touch file1.txt
[root@localhost ~]# [ -f file1.txt ] && echo yes || echo no
yes
//目录测试
[root@localhost ~]# [ -d /tmp ] && echo yes || echo no
yes
//测试文件属性
[root@localhost ~]# ll file1.txt
-rw-r--r-- 1 root root 0 8月 28 12:30 file1.txt
[root@localhost ~]# [ -r file1.txt ] && echo yes || echo no
yes
[root@localhost ~]# [ -x file1.txt ] && echo yes || echo no
no
//测试文件时间新旧
[root@wan ~]# mkdir  ex1.sh
[root@wan ~]# mkdir  ex2.sh
[root@wan ~]# [ ex1.sh -nt ex2.sh ]
[root@wan ~]# echo $?
1
[root@wan ~]# [ ex1.sh -ot ex2.sh ]
[root@wan ~]# echo $?
0

3.字符串测试

在这里插入图片描述

//-n如果字符串长度不为零输出yes,否则输出no
[root@localhost ~]# [ -n "hello" ] && echo yes || echo no
yes
[root@localhost ~]# [ -n "" ] && echo yes || echo no
no
//-z如果字符串长度为零输出yes,否则输出no
[root@localhost ~]# [ -z "hello" ] && echo yes || echo no
no
[root@localhost ~]# [ -z "" ] && echo yes || echo n
yes
// 字符串相等比较
注意:=的左右有空格,没有空格将会导致逻辑错误。
[root@localhost ~]# [ "HELO" = "hello" ] && echo yes || echo no
no
[root@localhost ~]# [ "HELO" != "hello" ] && echo yes || echo no
yes
4.整数测试

在这里插入图片描述

​ 示例:

[root@localhost ~]# [ 5 -gt 3 ] && echo yes || echo no
yes
[root@localhost ~]# [ `id -u` -eq 0 ] && echo admin || echo other
admin
[root@localhost ~]# su - student
[student@localhost ~]$ [ `id -u` -eq 0 ] && echo admin || echo other
other
5.逻辑运算符操作

在这里插入图片描述

[root@localhost ~]# [ -f /etc/hosts -a -f /etc/services ] && echo yes || echo no
yes
[root@localhost ~]# [[ -f /etc/hosts && -f /etc/services ]] && echo yes || echo
no
yes
6.命令执行顺序
; --命令的顺序执行# date ; ls -l /etc/passwd
&& --前面命令执行不成功,后面的命令不执行# mkdir /mnt/iso && mount /dev/sr0 /mnt/iso
|| --如果前面命令成功,后面就不执行,如果前面不成功后面就执行

ocalhost ~]# [ “HELO” != “hello” ] && echo yes || echo no
yes


#### 4.整数测试

[外链图片转存中...(img-mwj38RkR-1599835049075)]

​	示例:

```shell
[root@localhost ~]# [ 5 -gt 3 ] && echo yes || echo no
yes
[root@localhost ~]# [ `id -u` -eq 0 ] && echo admin || echo other
admin
[root@localhost ~]# su - student
[student@localhost ~]$ [ `id -u` -eq 0 ] && echo admin || echo other
other
5.逻辑运算符操作

[外链图片转存中…(img-qHXA8yXi-1599835049076)]

[root@localhost ~]# [ -f /etc/hosts -a -f /etc/services ] && echo yes || echo no
yes
[root@localhost ~]# [[ -f /etc/hosts && -f /etc/services ]] && echo yes || echo
no
yes
6.命令执行顺序
; --命令的顺序执行# date ; ls -l /etc/passwd
&& --前面命令执行不成功,后面的命令不执行# mkdir /mnt/iso && mount /dev/sr0 /mnt/iso
|| --如果前面命令成功,后面就不执行,如果前面不成功后面就执行
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值