Shell概念
在计算机科学中,shell俗称“壳”,是指提供使用者使用界面的软件(命令解析器)。类似于DOS下的command.com和后来的cmd.exe,它接收用户命令,然后调用相应的应用程序。
Shell是一个用C语言编写的程序,这个应用程序提供了一个界面,用户通过这个界面访问操作系统内核的服务。Ken Thompson的sh是第一种Unix Shell,Windows Explorer是一个典型的图形界面Shell。
Shell脚本是一种为shell编写的脚本程序。业界所说的shell通常都是指shell脚本,但读者朋友要知道,shell和shell script是两个不同的概念。本文出现的shell编程都是指shell脚本编程。
Shell环境
Shell编程跟java、php编程一样,只要有一个能编写代码的文本编辑器和一个能解释执行的脚本编辑器就可以了。
Linux的Shell种类众多,常见的有:
· Bourne Shell(/usr/bin/sh或/bin/sh)
· Bourne Again Shell(/bin/bash)
· C Shell(/usr/bin/csh)
· K Shell(/usr/bin/ksh)
· Shell for Root(/sbin/sh)
本教程关注的是Bash,也就是Bourne Again Shell,由于易用和免费,Bash在日常工作中被广泛使用。同时,Bash也是大多数Linux系统默认的Shell。在一般情况下,人们并不区分Bourne Shell和Bourne Again Shell,所以,像#!/bin/sh,它同样也可以改为#!/bin/bash。#!告诉系统其后路径所指定的程序即是解释此脚本文件的Shell程序。
Shell程序步骤:
1、创建一个文件,扩展名为.sh。
2、修改文件的权限为可执行文件。
3、执行。
Shell结构
1、#!用来指定执行脚本的shell。
2、# 注释。
3、命令和控制结构。
Shell变量
命名规则:
1、命名只能使用英文字母,数字和下划线,首个字符不能以数字开头。
2、中间不能有空格,可以使用下划线(_)。
3、不能使用标点符号。
4、不能使用bash里的关键字(可用help命令查看保留关键字)。
使用规则:
1、习惯用大写字母来命名变量。
2、赋值时,“=”前后不能有空格。
3、命令的执行结果赋值给变量时,使用反单引号 如:TIME=`date`。
4、使用变量时,使用$变量名 或 ${变量名}。
只读变量:
使用readonly,此命令可以将变量定义为只读变量,只读变量的值不能被改变。
如图,变量a为普通变量,可以被重新赋值;变量b定义为readonly,重新赋值会出错。
删除变量:
使用unset,变量删除后不能再次被使用,unset不能删除只读命令。
如图,定义了普通变量a和只读变量b,分别输出值,用unset命令删除,再次输出,普通变量不会再输出值;删除只读变量会出错,错误提示b不能被删除,是只读变量。
变量类型:
临时变量:也叫局部变量,在脚本或命令中定义,仅在当前shell实例中有效,其他shell启动的程序不能访问局部变量。
(以上案例中均为临时变量)
永久变量:也叫环境变量,所有的程序,包括shell启动的程序,都能访问环境变量,有些程序需要环境变量来保证其正常运行。必要的时候shell脚本也可以定义环境变量。
Shell字符串
字符串是shell编程中最常用最有用的数据类型(除了数字和字符串,也没啥其他类型好用了)字符串可以用单引号,也可以用双引号,也可以不用引号。
单引号:
1、单引号里的任何字符都会原样输出,单引号字符串中的变量是无效的;
2、单引号字符串中不能出现单引号(对单引号使用转义符后也不行)。
双引号:
1、双引号里可以有变量;
2、双引号里可以出现转义字符。
· 拼接字符串
两种方式:
1、无缝拼接
2、双引号内直接使用变量
· 获取字符串的长度
语法1: ${#name}
语法2: expr length “${name}”
· 提取子字符串
语法: ${name:startindex:length} #不包括startIndex处的字符
${name:0-index:length} #包括0-index处的字符
${name:startIndex} #不包括startIndex处的字符
${name:0-index} #包括0-index处的字符
还可以使用#、##、%、%%进行删除后保留子串。
#、##:从左边开始删除。
#表示从左边删除到第一个指定的字符;
##表示从左边删除到最后一个指定的字符。
%、%%:从右边开始删除。
%表示从右边删除到第一个指定的字符;
%%表示从右边删除到最后一个指定的字符。
删除包括了指定的字符本身。
str="This-is-a-test-string" #对字符串str进行截取
echo ${str#*-} #结果为is-a-test-string
echo ${str##*-} #结果为string
echo ${str%-*} #结果为This-is-a-test
echo ${str%%-*} #结果为This
· 查找子字符串
使用命令 expr。
· Shell数组
使用规则:
1、Bash仅仅支持一维数组,并且没有限定数组的大小。
2、数组元素的下标从0开始。
3、获取数组中的元素要利用下标。
4、下标使用不当,会报错。(可以大于最大下标,没有输出结果,不会报错;但如果下标为负数,则会报错)
定义数组:
语法1:arrayName=(值1 值2 …… 值n)
a=(1 2 3 4 5) #定义数组a
语法2:arrayName=(
值1
值2
……
值n
)
a=(
1
2
3
4
5
)
注意:元素间使用空格分隔开或者换行符。
或者直接定义数组的各个元素:
name[0]=值1
name[1]=值2
……
name[n]=值n
读取数组:
格式:${name[index]}
${a[0]} #读取数组a的第一个元素 输出1
获取数组所有元素:
格式:${name[*]} 或 ${name[@]}
${a[*]} #1 2 3 4 5
${a[@]} #1 2 3 4 5
获取数组长度:
格式:${#name[*]} 或 ${#name[@]}
${#a[*]} #5
${#a[@]} #5
位置变量和特殊变量
Shell解释用户执行的命令时,会将命令行的一串字符进行解析划分成部分。每个部分都有一个固定的变量名$n,不能自定义。
$n:n从0开始,依次往后+1。(从$1开始叫位置参数变量。大于等于10时,必须使用{}将数字括起来)
ex:ls -la file1 file2 file3 …… file10
$0 的值为:ls -la
$1 的值为:file1
……
${10} 的值为:file10
变量名称 | 意义 |
$* | 获取所有参数,合并一个字符串 |
$# | 参数个数 |
$$ | 当前进程的ID |
$! | 后台运行的最后一个进程的ID |
$? | 显示最后一个命令的退出状态。0表示没有错误 |
从键盘读取数据,赋值给变量。eg:read username
注意:当输入的词组个数大于需要的参数个数,则多出的词组将被作为整体被最后一个参数接收。
参数说明:
-p:输出提示文字
-n (num):输入字符串长度num,达到此长度,自动结束
-t (time):输入限制时间time
-s:隐藏输入内容
expr命令
对整数型变量进行算术运算
eg:expr 3 + 5
复杂计算:expr`expr 5 - 1` / 2
echo命令
用于字符串的输出显示
echo $var
开启转义:-e
\n:换行
\c:不换行
printf命令
与echo功能相同,用来输出,功能更强大,如格式化字符串,指定字符串的宽度,左右对齐方式,默认不换行,可以手动添加\n。语法:printf format-string [arguments……]
说明:format-string:格式控制字符串
arguments:参数值列表
%d %s %c %f格式替代符详解:
d:Decimal十进制整数--对应位置参数必须是十进制整数,否则报错!
s:string字符串--对应位置参数必须是字符串或者字符型,否则报错!
c:char字符--对应位置参数必须是字符串或者字符型,否则报错!
f:float浮点--对应位置参数必须是数字型,否则报错!
eg:printf "hello world" #不会换行
printf "hello world\n" #才会换行
printf %s abc def #此格式只制订了一个参数,但是多出的参数会复用这个指定的参数,按照该格式输出
没有参数时,%s为空,%d为0
转义序列 | 意义 |
\b | 退格 |
\f | 换页显示 |
\n | 换行 |
\r | 回车 |
\t | 水平制表符 |
\v | 垂直制表符 |
\\ | 转义斜杠 |