1、图形界面和命令行要达到的目的是一样的,都是让用户控制计算机。然而,真正能够控制计算机硬件(CPU、内存、显示器等)的只有操作系统内核(Kernel),图形界面和命令行只是架设在用户和内核之间的一座桥梁。
2、用户不能直接接触内核,这时候需要开发一个程序作为中间代理,将用户的操作需求转化为内核能接受的信息进行传入,而用户界面和命令行就是充当这个中间代理角色的程序。在Linux下,这个命令行就叫做Shell。
3、Shell也是一种编程语言,它的编译器(解释器)就是Shell这个程序,我们平时所说的Shell,有时是指连接用户和内核的这个程序,有时又是指Shell编程。
4、任何代码最终都要被“翻译”成二进制的形式才能在计算机中执行。有的编程语言,如 C/C++、Pascal、Go语言、汇编等,必须在程序运行之前将所有代码都翻译成二进制形式,也就是生成可执行文件,用户拿到的是最终生成的可执行文件,看不到源码,这个过程叫做编译,这样的编程语言叫做编译型语言,完成编译过程的软件叫做编译器。而有的编程语言,如 Shell、JavaScript、Python、PHP等,需要一边执行一边翻译,不会生成任何可执行文件,用户必须拿到源码才能运行程序。程序运行后会即时翻译,翻译完一部分执行一部分,不用等到所有代码都翻译完,这个过程叫做解释,完成解释过程的软件叫做解释器。
补充:编译型语言的优点是执行速度快、对硬件要求低、保密性好,适合开发操作系统、大型应用程序、数据库等。脚本语言的优点是使用灵活、部署容易、跨平台性好,非常适合Web开发以及小工具的制作。
1、sh
sh 的全称是 Bourne shell,由 AT&T 公司的 Steve Bourne开发,为了纪念他,就用他的名字命名了。sh 是 UNIX 上的标准 shell,很多 UNIX 版本都配有 sh。sh 是第一个流行的 Shell。
2、csh
sh 之后另一个广为流传的 shell 是由柏克莱大学的 Bill Joy 设计的,这个 shell 的语法有点类似C语言,所以才得名为 C shell ,简称为 csh。Bill Joy 是一个风云人物,他创立了 BSD 操作系统,开发了 vi 编辑器,还是 Sun 公司的创始人之一。BSD 是 UNIX 的一个重要分支,后人在此基础上发展出了很多现代的操作系统,最著名的有 FreeBSD、OpenBSD 和 NetBSD,就连 Mac OS X 在很大程度上也基于BSD。
3、tcsh
tcsh 是 csh 的增强版,加入了命令补全功能,提供了更加强大的语法支持。
4、ash
一个简单的轻量级的 Shell,占用资源少,适合运行于低内存环境,但是与下面讲到的 bash shell 完全兼容。
5、bash
bash shell 是 Linux 的默认 shell,本教程也基于 bash 编写。bash 由 GNU 组织开发,保持了对 sh shell 的兼容性,是各种 Linux 发行版默认配置的 shell。
6、查看当前系统支持的sh
$ cat /etc/shells
7、查看当前系统默认使用的sh
$ echo $SHELL
1、新建脚本文件,后缀随意,见名知意即可,eg : test.sh;
2、编辑内容如下:
#!/bin/bash
#声明本脚本使用的解释器
# Copyright (c) http://c.biancheng.net/shell/
#输出文字
echo "What is your name?"
#读取用户输入,并将用户输入内容赋值给PERSON变量
read PERSON
#输入变量内容
echo "Hello, $PERSON"
3、Shell脚本执行:
$ cd demo #切换到 test.sh 所在的目录
$ chmod +x ./test.sh #使脚本具有执行权限
$ ./test.sh #执行脚本
补充:使用点号“.”即使没有可执行权限依然能够运行。
1、变量
a. 变量不需要指明类型,直接赋值即可,也可以使用declare关键字显示定义变量的类型;
b. 变量定义方式:单引号、双引号、都不带;
c. 赋值号=的周围不能有空格;
d. 命名规则和大部分编程语言一致;
e. 变量输出时,需要在变量名前加$,而花括号{}可加可不加,加为了区分边界;
f. 只读变量声明:readonly;
g. 删除变量:unset variable_name
单引号和双引号的区别:前者原样输出内容,而后者存在变量是支持解释。
2、变量的作用域(Scope)
全局变量:当前会话有效,声明方式可以使用命令行直接声明,或者在脚本中声明。声明的变量在同一会话下都有效。
局部变量:脚本文件内的函数定义的变量,默认也是全局变量,只有在变量前显示使用local进行声明才是局部变量。
环境变量: 使用export关键字将变量导出,定义的变量在字Shell中也有效,但是关闭Shell会话后它就自动销毁。永久保留的方式是把环境变量写入启动文件。
3、给脚本传递位置参数
脚本test.sh代码如下:
#!/bin/bash
echo "Language: $1"
echo "URL: $2"
运行test.sh,并附带参数:
$ . ./a.sh Shell http://c.biancheng.net/shell/
4、给函数传递位置参数
脚本test.sh代码如下:
#!/bin/bash
#定义函数
function func(){
echo "Language: $1"
echo "URL: $2"
}
#调用函数
func C++ http://c.biancheng.net/cplus/
执行test.sh:
$. ./test.sh
5、特殊变量
变量 | 含义 |
---|---|
$0 | 当前脚本的文件名。 |
$n(n≥1) | 传递给脚本或函数的参数。n 是一个数字,表示第几个参数。例如,第一个参数是 $1,第二个参数是 $2。 |
$# | 传递给脚本或函数的参数个数。 |
$* | 传递给脚本或函数的所有参数。 |
$@ | 传递给脚本或函数的所有参数。当被双引号" "包含时,$@ 与 $* 稍有不同,我们将在《Shell ∗ 和 *和 ∗和@的区别》一节中详细讲解。 |
$? | 上个命令的退出状态,或函数的返回值,我们将在《Shell $?》一节中详细讲解。 |
$$ | 当前 Shell 进程 ID。对于 Shell 脚本,就是这些脚本所在的进程 ID。 |
∗ 与 *与 ∗与@区别:当被“”包围时,前者将所有的参数从整体上看做是一份数据,而不是把每一个参数都看做一份数据,for循环时,只循环一遍,而后者则将每一个参数作为一份数据,彼此之间独立。
6、Shell命令替换: 理解为将指令的执行结果赋值给变量
示例:
#方式一:使用反应号将指令包围
var_name1 = `date`
#方式二:使用$()将指令包围
var_name2 = $(date)
echo $var_name1
echo $var_name2
注意:变量输出时,不使用“”包围的话,换行符、连续空白等格式都将会被压缩成一个空格,而使用“”包围则会按照原样格式进行输出。
7、字符串
获取字符串的长度:
#!/bin/bash
str="http://c.biancheng.net/shell/"
echo ${$str}
**字符串连接:**直接将变量并在一起即可
#!/bin/bash
#全是变量
name="Shell"
url="http://c.bian.com"
str1=$name$url #没被任何一种引号包围时,不能有空格,否则被误认为字符串结束
str2="$name $url" #中间允许有空格
#非全变量
str3=$name":"$url #中间允许其他符号
str4="${name}Script:${url}index.html"
echo $str1
echo $str2
echo $str3
echo $str4
字符串截取:
(1)从指定位置开始截取
#!/bin/bash
url="c.biancheng.net"
#从左边开始计数
echo ${url:2:9} #从第2个字符开始,截取九个长度的字符串
echo ${url:2} #从第2个字符开始,截取到末尾
#从右边开始计数
echo ${url:0-13:9}
echo ${url:0-13} #截取到末尾
(2)从指定字符串开始截取
特点:这种截取方式无法指定字符串的长度,只能从指定字符开始截到末尾,但可以选择右边所有字符或者左边所有字符
使用#截取右边所有字符:从左往右
#!/bin/bash
url="http://test.com"
#使用#指定获取字符右边的所有字符,其中*是表示忽略左边的字符
echo ${url#*:} #结果输出://test.com
echo ${url#:} #结果输出:http://test.com
#使用#默认匹配从左往右首个匹配到的字符,若要匹配最后一个匹配的字符,则使用两个#
url="http://test.com/index.html"
echo ${url#*/} #结果输出:/test.com/index.html
echo ${url##*/} #结果输出:index.html
使用%截取左边所有字符:从右往左
#!/bin/bash
url="http://c.biancheng.net/index.html"
echo ${url%/*} #结果为 http://c.biancheng.net
echo ${url%%/*} #结果为 http:
str="---aa+++aa@@@"
echo ${str%aa*} #结果为 ---aa+++
echo ${str%%aa*} #结果为 ---
两者用法一致,方向相反而已。
8、Shell数组:
Shell并没有限制数组的大小,理论上可以存放无限量的数据。数组元素的下标也是从0开始计数,获取数组中的元素要使用下标[]。常用的Bash Shell只支持以为数组,不支持多为数组。
数组定义
#数组元素之间使用空格分隔,数组元素不要求类型相同
num=(20 39 49 55 "http://test.com")
#追加元素
num[5]=88
#给指定元素赋值
ages=([3]=23 [5]=19 [10]=12)
获取数组元素
#获取单个元素值
n=${nums[2]}
#获取所有元素值
${nums[*]}
${nums[@]}
nums=(29 100 13 8 91 44)
echo ${nums[@]} #输出所有数组元素
nums[10]=66 #给第10个元素赋值(此时会增加数组长度)
echo ${nums[*]} #输出所有数组元素
echo ${nums[4]} #输出第4个元素
运行结果:
29 100 13 8 91 44
29 100 13 8 91 44 66
91
获取数组长度
使用@或者*,可以将数组扩展成为列表,然后使用#来获取数组的个数:
#!/bin/bash
nums=(29 100 13)
echo ${#nums[*]}
#向数组中添加元素
nums[10]="http://c.biancheng.net/shell/"
echo ${#nums[@]}
echo ${#nums[10]}
#删除数组元素
unset nums[1]
echo ${#nums[*]
运行结果:
3
4
29
3
数组拼接
拼接数组的思路是:先利用@或*,将数组扩展成列表,然后再合并到一起。示例如下:
#!/bin/bash
array1=(23 56)
array2=(99 "http://c.biancheng.net/shell/")
array_new=(${array1[@]} ${array2[*]})
echo ${array_new[@]} #也可以写作 ${array_new[*]}
#运行结果:
#23 56 99 http://c.biancheng.net/shell/
删除数组
在 Shell 中,使用 unset 关键字来删除数组元素,具体示例如下:
#!/bin/bash
arr=(23 56 99 "http://c.biancheng.net/shell/")
unset arr[1]
echo ${arr[@]}
unset arr
echo ${arr[*]}
#运行结果:
#23 99 http://c.biancheng.net/shell/
#
9、Shell内建指令(内置指令)
所谓 Shell 内建命令,就是由 Bash 自身提供的命令,而不是文件系统中的某个可执行文件。
10、Shell alias:给命令创建别名
查看那些指令被默认创建了别名;
[root@localhost ~]# alias
alias cp='cp -i'
alias l.='ls -d .* --color=tty'
alias ll='ls -l --color=tty'
alias ls='ls --color=tty'
alias mv='mv -i'
alias rm='rm -i'
alias which='alias | /usr/bin/which --tty-only --read-alias --show-dot --show-tilde'
自定义别名:使用 alias 定义的别名命令也是支持 Tab 键补全的
alias myShutdown='shutdown -h now'
注意,这样定义别名只能在当前 Shell 环境中有效,换句话说,重新登录后这个别名就消失了。为了确保永远生效,可以将该别名手动写入到用户主目录中的.bashrc文件。
.bashrc其实也是一个 Shell 脚本文件,该文件专门用来存放用户自定义的别名和函数。
将别名写入.bashrc文件后的效果如下所示:
# .bashrc
# User specific aliases and functions
alias myShutdown='shutdown -h now'
# Source global definitions
if [ -f /etc/bashrc ]; then
. /etc/bashrc
fi
unalias:删除别名
使用 unalias 内建命令可以删除当前 Shell 环境中的别名。unalias 有两种使用方法:
同样,这两种方法都是在当前 Shell 环境中生效的。要想永久删除在.bashrc文件中定义的别名,只能进入该文件手动删除。
11、echo命令
(1)添加-n参数不换行;
(2)添加-e参数显示转义字符;
(3)添加-e参数,配合\c转义字符强制不换行;
12、exit命令
(1)脚本内执行exit,结束代码运行,退出Shell脚本;
(2)终端执行exit,退出当前登录的Shell,并结束终端;
13、Shell ulimit命令:显示并设置进程资源限度
系统的可用资源是有限的,如果不限制用户和进程对系统资源的使用,则很容易陷入资源耗尽的地步,而使用 ulimit 命令可以控制进程对可用资源的访问(ulimit 是一个 Shell 内置命令)。
默认情况下 Linux 系统的各个资源都做了软硬限制,其中硬限制的作用是控制软限制(换言之,软限制不能高于硬限制)。使用ulimit -a可以查看当前系统的软限制,使用命令ulimit -a –H可查看系统的硬限制。