Shell编程 第 1~5章
第 1 章 Shell 概述、第 2 章 Shell 脚本入门、第 3 章 变量、第 4 章 运算符、第 5 章 条件判断
第 1 章 Shell 概述
什么是Shell
-
在计算机科学中,Shell俗称壳(用来区别于核),是指“为使用者提供操作界面”的软件(command interpreter,命令解析器)。它类似于DOS下的COMMAND.COM和后来的cmd.exe。它接收用户命令,然后调用相应的应用程序。
-
同时它又是一种程序设计语言。作为命令语言,它交互式解释和执行用户输入的命令或者自动地解释和执行预先设定好的一连串的命令;作为程序设计语言,它定义了各种变量和参数,并提供了许多在高级语言中才具有的控制结构,包括循环和分支。在排序算法中,Shell是希尔排序的名称。
-
Shell是一个命令行解释器,它为用户提供了一个向Linux内核发送请求以便运行程序的界面系统级程序,用户可以用Shell来启动、挂起、停止甚至是编写一些程序。
-
Shell还是一个功能强大的编程语言,易编写,易调试,灵活性较强。Shell是解释执行的脚本语言,在Shell中可以直接调用Linux系统命令。
Shell分类
-
Bourne Shell:从1979年起Unix就开始使用Bourne Shell,Bourne Shell的主文件名为sh。
-
C Shell:C Shell主要在BSD版的Unix系统中使用,其语法和C语言相似而得名。
Shell的两种主要语法类型有Bourne和C,这两种语法彼此不兼容。
Bourne家族主要包括sh, ksh, Bash, psh, zsh;C家族主要包括:csh,tcsh.
- Bash:Bash和sh兼容,现在使用的Linux就是使用Bash作为用户的基本Shell。
Linux 提供的 Shell 解析器
[root@hadoop100 ~]# cat /etc/shells
/bin/sh
/bin/bash
/usr/bin/sh
/usr/bin/bash
/bin/tcsh
/bin/csh
bash 和 sh 的关系
[root@hadoop100 ~]# ls -l /bin/ | grep bash
-rwxr-xr-x. 1 root root 964536 11月 25 2021 bash
lrwxrwxrwx. 1 root root 10 12月 3 10:59 bashbug -> bashbug-64
-rwxr-xr-x. 1 root root 6964 11月 25 2021 bashbug-64
lrwxrwxrwx. 1 root root 4 12月 3 10:59 sh -> bash
Centos 默认的解析器是 bash
[root@hadoop100 ~]# echo $SHELL
/bin/bash
第 2 章 Shell 脚本入门
脚本格式
脚本以#!/bin/bash
开头(指定解析器)
第一个 Shell 脚本:helloworld.sh
需求:创建一个 Shell 脚本,输出 helloworld
- 输入
mkdir scripts
创建一个目录 - 输入
cd scripts/
进入目录 - 输入
touch hello.sh
创建脚本文件 - 输入
vim hello.sh
添加脚本内容
#!/bin/bash
echo "hello,world"
- 执行脚本第一种:采用 bash 或 sh + 脚本的相对路径或绝对路径(不用赋予脚本+x 权限)
执行脚本方法一: (bash 相对路径)
[root@hadoop100 scripts]# bash hello.sh
hello,world
[root@hadoop100 scripts]# bash ./hello.sh
hello,world
执行脚本方法二: (bash 相对路径)
[root@hadoop100 scripts]# cd ~
[root@hadoop100 ~]# bash scripts/hello.sh
hello,world
执行脚本方法三: (bash 绝对路径)
[root@hadoop100 ~]# bash /root/scripts/hello.sh
hello,world
执行脚本方法四: (sh 相对路径)
[root@hadoop100 ~]# sh scripts/hello.sh
hello,world
- 第二种:采用输入脚本的绝对路径或相对路径执行脚本(必须具有可执行权限+x)
输入chmod +x scripts/hello.sh
添加执行权限
[root@hadoop100 ~]# chmod +x scripts/hello.sh
[root@hadoop100 ~]# ll scripts/
总用量 4
-rwxr-xr-x. 1 root root 31 12月 22 19:15 hello.sh
绝对路径输入 /root/scripts/hello.sh
执行脚本
[root@hadoop100 ~]# /root/scripts/hello.sh
hello,world
相对路径 输入 ./hello.sh
在父级目录时不能直接输入脚本执行要加./ 在创建一个子bash打开
[root@hadoop100 scripts]# hello.sh
bash: hello.sh: 未找到命令...
[root@hadoop100 scripts]# ./hello.sh
hello,world
- 在脚本的路径前加上“.”或者 source
[root@hadoop100 scripts]# source hello.sh
hello,world
[root@hadoop100 scripts]# source /root/scripts/hello.sh
hello,world
[root@hadoop100 scripts]# . hello.sh
hello,world
[root@hadoop100 scripts]# type source
source 是 shell 内嵌
- 原因
前两种方式都是在当前 shell 中打开一个子 shell 来执行脚本内容,当脚本内容结束,则子 shell 关闭,回到父 shell 中。
第三种,也就是使用在脚本路径前加“.”或者 source 的方式,可以使脚本内容在当前shell 里执行,而无需打开子 shell!这也是为什么我们每次要修改完/etc/profile 文件以后,需要 source 一下的原因。
开子 shell 与不开子 shell 的区别就在于,环境变量的继承关系,如在子shell 中设置的当前变量,父 shell 是不可见的。
[root@hadoop100 scripts]# ps -f
UID PID PPID C STIME TTY TIME CMD
root 1839 1831 0 16:18 pts/0 00:00:00 -bash
root 4232 1839 0 19:58 pts/0 00:00:00 ps -f
[root@hadoop100 scripts]# bash
子bash
[root@hadoop100 scripts]# ps -f
UID PID PPID C STIME TTY TIME CMD
root 1839 1831 0 16:18 pts/0 00:00:00 -bash
root 4233 1839 0 19:58 pts/0 00:00:00 bash
root 4267 4233 0 19:58 pts/0 00:00:00 ps -f
[root@hadoop100 scripts]# ./hello.sh
hello,world
[root@hadoop100 scripts]# exit
exit
父bash
[root@hadoop100 scripts]# ps -f
UID PID PPID C STIME TTY TIME CMD
root 1839 1831 0 16:18 pts/0 00:00:00 -bash
root 4277 1839 0 19:59 pts/0 00:00:00 ps -f
第 3 章 变量
3.1 系统预定义变量
常用系统变量
$HOME、$PWD、$SHELL、$USER
等
操作
- 查看系统变量的值
[root@hadoop100 scripts]# echo $HOME
/root
2 . 显示当前 Shell 中所有变量:set
输入 set | less
ABRT_DEBUG_LOG=/dev/null
BASH=/bin/bash
BASHOPTS=checkwinsize:cmdhist:expand_aliases:extglob:extquote:force_fignore:histappend:interactive_comments:login_shell:progcomp:promptvars:sourcepath
BASH_ALIASES=()
BASH_ARGC=()
BASH_ARGV=()
BASH_CMDS=()
BASH_COMPLETION_COMPAT_DIR=/etc/bash_completion.d
BASH_LINENO=()
BASH_SOURCE=()
BASH_VERSINFO=([0]="4" [1]="2" [2]="46" [3]="2" [4]="release" [5]="x86_64-redhat-linux-gnu")
BASH_VERSION='4.2.46(2)-release'
COLUMNS=85
DIRSTACK=()
DISPLAY=localhost:10.0
EUID=0
GLUSTER_BARRIER_OPTIONS=$'\n {enable},\n {disable}\n'
3.2 自定义变量
语法
(1)定义变量:变量名=变量值
,注意,=号前后不能有空格
(2)撤销变量:unset 变量名
(3)声明静态变量:readonly 变量
,注意:不能 unset
变量定义规则
(1)变量名称可以由字母、数字和下划线组成,但是不能以数字开头,环境变量名建议大写。
(2)等号两侧不能有空格
(3)在 bash 中,变量默认类型都是字符串类型,无法直接进行数值运算。
(4)变量的值如果有空格,需要使用双引号或单引号括起来。
操作
- 定义变量 a
[root@hadoop100 scripts]# a=2
[root@hadoop100 scripts]# echo $a
2
- 先定义,后赋值
[root@hadoop100 scripts]# echo $my_var
[root@hadoop100 scripts]# my_var=hello
[root@hadoop100 scripts]# echo $my_var
hello
- 输出字符串有空格 用""或''
[root@hadoop100 scripts]# my_var = Hello
bash: my_var: 未找到命令...
[root@hadoop100 scripts]# my_var=Hello
[root@hadoop100 scripts]# my_var=Hello, world
bash: world: 未找到命令...
[root@hadoop100 scripts]# my_var="Hello, world"
[root@hadoop100 scripts]# echo $my_var
Hello, world
[root@hadoop100 scripts]# my_var='Hello, world'
[root@hadoop100 scripts]# echo $my_var
Hello, world
- 此时只是局部变量子shell用不了
输入bash
创建子bash
输入exit
退出到父bash
[root@hadoop100 scripts]# env | grep my_var
[root@hadoop100 scripts]# set | grep my_var
my_var='Hello, world'
[root@hadoop100 scripts]# bash
[root@hadoop100 scripts]# ps -f
UID PID PPID C STIME TTY TIME CMD
root 4705 4688 0 20:28 pts/0 00:00:00 -bash
root 4864 4705 1 20:36 pts/0 00:00:00 bash
root 4897 4864 0 20:36 pts/0 00:00:00 ps -f
[root@hadoop100 scripts]# echo $my_var
[root@hadoop100 scripts]# exit
exit
[root@hadoop100 scripts]# echo $my_var
Hello, world
-
把变量提升为全局环境变量,可供其他 Shell 程序使用
语法 export 变量名
-
给hello.sh 添加 echo $my_var 用相对目录./新的子bash打开 my_var是全局变量可查看
[root@hadoop100 scripts]# vim hello.sh
[root@hadoop100 scripts]# cat hello.sh
#!/bin/bash
echo "hello,world"
echo $my_var
[root@hadoop100 scripts]# source hello.sh
hello,world
Hello, world
[root@hadoop100 scripts]# ./hello.sh
hello,world
Hello, world
- 测试子bash
(1) 新定义变量
[root@hadoop100 scripts]# echo $new_var
[root@hadoop100 scripts]# new_var="new_var hello, linux"
[root@hadoop100 scripts]# echo $new_var
new_var hello, linux
(2)新定义变量放入脚本
[root@hadoop100 scripts]# vim hello.sh
[root@hadoop100 scripts]# cat hello.sh
#!/bin/bash
echo "hello,world"
echo $my_var
echo $new_var
(3)新子bash打开无法查看
[root@hadoop100 scripts]# ./hello.sh
hello,world
Hello, world
(4)父bash可以查看
[root@hadoop100 scripts]# . hello.sh
hello,world
Hello, world
new_var hello, linux
(5)提升new_var为全局变量,子bash可以查看
[root@hadoop100 scripts]# export new_var
[root@hadoop100 scripts]# ./hello.sh
hello,world
Hello, world
new_var hello, linux
- 输出数字相加
[root@hadoop100 ~]# echo $a
[root@hadoop100 ~]# a=1+5
[root@hadoop100 ~]# echo $a
1+5
[root@hadoop100 ~]# echo a
a
[root@hadoop100 ~]# a=$((1+5))
[root@hadoop100 ~]# echo $a
6
[root@hadoop100 ~]# a=$[5+9]
[root@hadoop100 ~]# echo $a
14
- 静态变量(常量)定义,且无法撤销
[root@hadoop100 ~]# readonly b=5
[root@hadoop100 ~]# b=10
-bash: b: 只读变量
[root@hadoop100 ~]# echo $b
5
[root@hadoop100 ~]# unset b
-bash: unset: b: 无法反设定: 只读 variable
- 撤销变量
[root@hadoop100 ~]# unset a
[root@hadoop100 ~]# echo $a
[root@hadoop100 ~]#
3.3 特殊变量
3.3.1 $n
语法
$n
(功能描述:n 为数字,$0 代表该脚本名称,$1-\(9 代表第一到第九个参数,
十以上的参数,十以上的参数需要用大括号包含,如\){10})
操作
[root@hadoop100 scripts]# vim parameter.sh
[root@hadoop100 scripts]# cat parameter.sh
#!/bin/bash
echo '==========$n=========='
echo script name: $0
echo 1st paramater: $1
echo 2nd parameter: $2
[root@hadoop100 scripts]# ll
总用量 8
-rwxr-xr-x. 1 root root 47 12月 23 09:27 hello.sh
-rw-r--r--. 1 root root 109 12月 23 09:43 parameter.sh
[root@hadoop100 scripts]# chmod +x parameter.sh
[root@hadoop100 scripts]# ll
总用量 8
-rwxr-xr-x. 1 root root 47 12月 23 09:27 hello.sh
-rwxr-xr-x. 1 root root 109 12月 23 09:43 parameter.sh
[root@hadoop100 scripts]# ./parameter.sh abc def
==========$n==========
script name: ./parameter.sh
1st paramater: abc
2nd parameter: def
3.3.2 $#
语法
$#
(功能描述:获取所有输入参数个数,常用于循环,判断参数的个数是否正确以及加强脚本的健壮性)。
操作
[root@hadoop100 scripts]# vim parameter.sh
[root@hadoop100 scripts]# cat parameter.sh
#!/bin/bash
echo '==========$n=========='
echo script name: $0
echo 1st paramater: $1
echo 2nd parameter: $2
echo '==========$#=========='
echo parameter numbers: $#
[root@hadoop100 scripts]# ./parameter.sh
==========$n==========
script name: ./parameter.sh
1st paramater:
2nd parameter:
==========$#==========
parameter numbers: 0
[root@hadoop100 scripts]# ./parameter.sh abc def
==========$n==========
script name: ./parameter.sh
1st paramater: abc
2nd parameter: def
==========$#==========
parameter numbers: 2
3.3.3 $*
、$@
参数
语法
$*
(功能描述:这个变量代表命令行中所有的参数,$*
把所有的参数看成一个整体)
$@
(功能描述:这个变量也代表命令行中所有的参数,不过$@
把每个参数区分对待)
3.3.4 $?
语法
$?
(功能描述:最后一次执行的命令的返回状态。如果这个变量的值为0,证明上一个命令正确执行;如果这个变量的值为非 0(具体是哪个数,由命令自己来决定),则证明上一个命令执行不正确了。)
操作
判断 helloworld.sh 脚本是否正确执行
[atguigu@hadoop101 shells]$ ./helloworld.sh
hello world
[atguigu@hadoop101 shells]$ echo $?
0
操作
说明
echo '==========$n=========='
加上''单引号和=等于号是为了原封不动输出,不看成是变量,测试用
[atguigu@hadoop101 shells]$ vim parameter.sh
#!/bin/bash
echo '==========$n=========='
echo $0
echo $1
echo $2
echo '==========$#=========='
echo $#
echo '==========$*=========='
echo $*
echo '==========$@=========='
echo $@
[atguigu@hadoop101 shells]$ chmod 777 parameter.sh
[atguigu@hadoop101 shells]$ ./parameter.sh a b c d e f g
==========$n==========
./parameter.sh
a
b
==========$#==========
7
==========$*==========
a b c d e f g
==========$@==========
a b c d e f g
第 4 章 运算符
语法
“$((运算式))” 或 “$[运算式]”
expr 1 + 2
操作
计算(2+3)* 4 的值
[root@hadoop100 scripts]# S=$[(2+3)*4]
[root@hadoop100 scripts]# echo $S
20
expr
[root@hadoop100 scripts]# expr 1 + 2
3
[root@hadoop100 scripts]# expr 5 - 2
3
[root@hadoop100 scripts]# expr 5 * 2
expr: 语法错误
[root@hadoop100 scripts]# expr 5 \* 2
10
脚本运算
[root@hadoop100 scripts]# vim add.sh
[root@hadoop100 scripts]# cat add.sh
#!/bin/bash
sum=$[$1 + $2]
echo sum=$sum
[root@hadoop100 scripts]# chmod +x add.sh
[root@hadoop100 scripts]# ./add.sh 2 5
sum=7
第 5 章 条件判断
语法
(1)test condition
(condition判断条件)
(2)[ condition ]
(注意 condition 前后要有空格)(常用)
注意:条件非空即为 true,[ atguigu ]返回 true,[ ] 返回 false。
常用判断条件
(1)两个整数之间比较
-eq 等于(equal) -ne 不等于(not equal)
-lt 小于(less than) -le 小于等于(less equal)
-gt 大于(greater than) -ge 大于等于(greater equal)
注:如果是字符串之间的比较 ,用等号“=”判断相等;用“!=”判断不等。
(2)按照文件权限进行判断
-r 有读的权限(read)
-w 有写的权限(write)
-x 有执行的权限(execute)
(3)按照文件类型进行判断
-e 文件存在(existence)
-f 文件存在并且是一个常规的文件(file)
-d 文件存在并且是一个目录(directory)
操作
test condition
方法一
[root@hadoop100 scripts]# a=hello
[root@hadoop100 scripts]# echo $a
hello
[root@hadoop100 scripts]# test $a = hello
[root@hadoop100 scripts]# echo $?
0
[root@hadoop100 scripts]# test $a = Hello
[root@hadoop100 scripts]# echo $?
1
[root@hadoop100 scripts]# a=Hello
[root@hadoop100 scripts]# test $a=Hello
[root@hadoop100 scripts]# echo $?
0
[ condition ]
方法二
[root@hadoop100 scripts]# a=Hello
[root@hadoop100 scripts]# [ $a = Hello ]
[root@hadoop100 scripts]# echo $?
0
[root@hadoop100 scripts]# [ $a = hello ]
[root@hadoop100 scripts]# echo $?
1
[root@hadoop100 scripts]# [ $a != Hello ]
[root@hadoop100 scripts]# echo $?
1
- 方法二要使用空格,不用会看成整体或报错
[root@hadoop100 scripts]# [ $a=hello ]
[root@hadoop100 scripts]# echo $?
0
[root@hadoop100 scripts]# [ aasdasfas ]
[root@hadoop100 scripts]# echo $?
0
[root@hadoop100 scripts]# [ ]
[root@hadoop100 scripts]# echo $?
1
- 23 是否大于等于 22
[atguigu@hadoop101 shells]$ [ 23 -ge 22 ]
[atguigu@hadoop101 shells]$ echo $?
0
- hello.sh 是否具有写权限
[root@hadoop100 scripts]# [ -w hello.sh ]
[root@hadoop100 scripts]# echo $?
0
- info文件是否存在
[root@hadoop100 scripts]# [ -e /home/mr155/info ]
[root@hadoop100 scripts]# echo $?
1
[root@hadoop100 scripts]# ls /home/mr155/
anaconda-ks.cfg initial-setup-ks.cfg 公共 视频 文档 音乐
Desktop myFolder 模板 图片 下载 桌面
- 多条件判断(&& 表示前一条命令执行成功时,才执行后一条命令,|| 表示上一条命令执行失败后,才执行下一条命令)
[atguigu@hadoop101 ~]$ [ atguigu ] && echo OK || echo notOK
OK
[atguigu@hadoop101 shells]$ [ ] && echo OK || echo notOK
notOK
[root@hadoop100 scripts]# a=15
[root@hadoop100 scripts]# [ $a -lt 20 ] && echo "$a < 20" || echo "$a >= 20"
15 < 20
[root@hadoop100 scripts]# a=27
[root@hadoop100 scripts]# [ $a -lt 20 ] && echo "$a < 20" || echo "$a >= 20"
27 >= 2
标签:Shell,编程,echo,sh,scripts,hadoop100,root,hello
From: https://www.cnblogs.com/mr155/p/16998967.html