Shell介绍
Shell 是一个用 C 语言编写的程序,文件格式未*.sh,它是用户使用 Linux 的桥梁,开发者还可以通过这个Shell访问操作系统的内核服务。
Shell的应用范围
在安卓方面可用来编译动态库,俗称.so文件。
在ios方面可以用来编译静态库,俗称.a文件。
其他作用多多,不再枚举。
Shell环境
Shell 编程跟 JavaScript、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,测试环境就在macos上。
执行Shell脚本
首先我们可以打开终端创建一个helloworld程序
touch helloworld.sh
然后开始编写我们的第一个脚本,终端打开脚本文件
open helloworld.sh
输入一下代码
#!/bin/bash
echo "Helloworld!"
#!:约定符,告诉系统这个脚本需要用什么解释器来执行,是脚本语言通用的约定符号。
echo:打印/输出命令,在shell中调用命令的规则是:命令+空格+参数,此处echo为命令,空格后面加输出内容
此时我们可以测试一下这个简单的shell脚本,在macOS中,终端运行脚本只需要出入脚本路径,规则是:脚本路径+空格+参数,如果没有参数就只需要脚本路径,在终端执行测试脚本,例如(没有参数就不写):
./helloworld.sh 参数1 参数2 参数3...
但是你会发现终端提示如下错误:
permission denied: ./helloworld.sh
这是因为该脚本文件还没有可执行的权限,同时我们也可以查看一下该脚本的权限,终端输入:
ls -l helloworld.sh
终端打印出:-rw-r--r--@ 1 max staff 32 5 9 11:05 helloworld.sh
我们只需要看加粗部分,加粗部分共有9位,其中结构如下图
d:文件目录
r:读取
w:写入
x:可执行
-:没有/不是
可以发现我们的脚本文件是没有可执行权限(X)的,于是我们需要给它加上执行权限
chmod +X helloworld.sh
这句话的意思是给属主和与属主同组下的所有用户分配该文件的执行权限
然后我们再执行shell脚本就可以正常运行了
Shell注释
shell中没有多行注释,只有单行注释,只需在需要注释的行首加上“#”即可。
Shell语法
变量
为了不造成不必要的麻烦,请遵从以下规则
注意一:变量名首字母及其组成必需是字母(a-z、A-Z)或者下划线
注意二:变量名和等号不能够有空格,且任何等号两边都不要空格,因为有了空格后,系统会默认为等号左边的是一个命令,而系统又找不到这个命令,例如:
name = "Junnpy"
执行后终端会打印:
./helloworld.sh: line 5: name: command not found
只读变量:readonly 变量名,被申明成只读后不能被修改
删除变量 :unset 变量名,变量被删除后不能使用,因为属于未定义状态
变量类型
类型一:本地变量,作用域整个bash进程可以使用,就是普通的变量定义,如:
name="Junnpy"
类型二:局部变量,作用域为当前代码段,用“local”修饰,如:
local name="Junnpy"
类型三:环境变量,作用域为当前shell进程以及子进程,用“export”修饰,如:
export name="Junnpy"
类型四:特殊变量
$$:获取当前shell进程ID
$!:获取执行上一个指令的PID
${?}:表示返回上一个命令执行状态返回值,值为0表示成功,其他表示错误切返回错误码,常见的错误码如下图:
Shell脚本语言-传递参数
#!/bin/bash
path=${0}
name=${1}
age=${2}
sex=${3}
echo "脚本路径:${path} 姓名:${name} 年龄:${age} 性别:${sex} "
终端输入:
./helloworld.sh Junnpy 150 男
输出:
脚本路径:./helloworld.sh 姓名:Junnpy 年龄:150 性别:男
可以发现shell中取变量的值格式为:${变量名},而这种${数字}的取值方式是为了取出用户输入的参数,而且下标为0的始终会有值,不管用户是否传入参数,因为这是脚本的路径,而且是相对路径,系统自带,要获取用户的输入参数就得从1开始
$#:获取用户传入参数个数
$* 或者 $@:获取用户传入参数列表
Shell字符串
在shell语言中,字符串不区分双引号和单引号,例如:
name="Junnpy"
name2='Junnpy'
都可以视为字符串。
Shell字符串长度
name="Junnpy"
echo ${#name}
Shell字符串拼接
方式一:
脚本代码
#!/bin/bash
name="Junnpy"
age=100
sex="男"
info="${name} ${age} ${sex}"
echo ${info}
脚本结果:
Junnpy 100 男
方式二:
脚本代码
#!/bin/bash
name="Junnpy"
age=100
sex="男"
info=" 姓名:"${name}" 年龄:"${age}" 性别:"${sex}" "
echo ${info}
脚本结果:
姓名:Junnpy 年龄:100 性别:男
获取Shell字符串长度
语法结构:${#变量名}
脚本代码
#!/bin/bash
name="Junnpy"
echo ${#name}
脚本结果:
6
Shell字符串截取
语法:${变量名:开始位置:截取长度}
脚本代码
#!/bin/bash
name="Ihave a Dream"
案例一:从字符串第3个开始截取,截取3个
name="I have a Dream"
result=${name:2:3}
echo ${result}
案例二:从字符串第5个开始截取,到最后一个结束
方式一
name="I have a Dream"
length=${#name}
result=${name:5:length-1}
echo ${result}
方式二
name="I have a Dream"
result=${name:5}
echo ${result}
Shell字符串删除
语法一:${变量名#删除字符串 正则表达式}
作用:从字符串头部开始匹配要删除字符串,从头部匹配这很重要
案例一: 删除“Dream”
name="Ihave a Dream"
result=${name#Dream}
echo ${result}
删除失败,原因:匹配不到,因为头部没有‘Dream’这个字符串
案例二: 删除“I”
name="I have a Dream"
result=${name#I}
echo ${result}
输出:
have a Dream
这种方式被删除后会同时自动删除头部的所有空格
案例三:查找指定字符第一个,并且删除前面所有的字符(包含自己),删除“D”之前的包括自己
name="I have a Dream"
result=${name#*D}
echo ${result}
案例四:指定删除范围,删除“I”到“D”
name="I have a Dream"
result=${name#I*D}
echo ${result}
语法二:${变量名##删除字符串 正则表达式}
作用:从字符串末尾开始匹配要删除字符串,从末尾开始这很重要
案例一:删除‘a’之前的所有包括自己
name="I have a Dream"
result=${name##*a}
echo ${result}
总结:语法一和语法二,都是从左边删除到右边,只是查找方向不一样
语法三:${变量名%删除字符串 正则表达式}
作用:从字符串结尾开始匹配,删除匹配的字符串,从末尾开始这很重要
案例一:删除‘a’
代码一:
name="I have a Dream"
result=${name%a}
echo${result}
删除失败,原因:匹配不到,因为尾部是‘m’,不是‘a’
代码二:删除‘m’
name="I have a Dream"
result=${name%m}
echo${result}
案例二:查找指定字符第一个,并且删除后面所有字符(包含自己),删除‘h’之后所有字符串包括自己
name="I have a Dream"
result=${name%h*}
echo ${result}
案例三:指定删除范围,删除‘D’到‘m’,他会先匹配‘m’,因为要遵从末尾开始匹配的规则,如果找不到‘m’则删除失败
name="I have a Dream"
result=${name%D*m}
echo ${result}
语法四:${变量名%%删除字符串 正则表达式}
案例一:查找指定字符最后一个(这个查找从末尾开始),并且删除前面所有的字符(包含自己)
name="I have a Dream"
result=${name%%a*}
echo ${result}
总结:
从左边删除到右边
#->表示查询方向从左到右
##->表示查询方向从右到左
从右边删除到左边
%->表示查询方向从右到左
%%->表示查询方向从左到右
ps:那如何删除shell字符串中间某部分呢,系统并没有提供直接的方法,但可以有折中的方法:
echo '删除中间字符串 例如:删掉www.abc.com'
var=http://www.abc.com/123.html
echo '删除前:'$var
echo'删除后:'${var%%www*} ${var##*com}