shell概述

bash及其特性:
shell: 外壳
GUI:Gnome, KDE, Xfce
CLI: sh, csh, ksh, bash, tcsh, zsh

程序:进程的关系

root, student
程序:进程

进程:在每个进程看来,当前主机上只存在内核和当前进程
进程是程序的副本,进程是程序执行实例

用户工作环境:
bash:
# 管理员界面
$ 用户界面
shell作为命令解释程序 是一种高级程序设计语言,它有变量,关键字,有各种控制语句,如if、case、while、for等语句,支持函数模块,有自己的语法结构。

目录

shell的主要特点、类型、建立和执行的方式

1. shell的特点

☆ 组合新命令
☆ 提供了文件名扩展字符
☆ 直接使用shell的内置命令
☆ 灵活地使用数据流
☆ 结构化的程序模块
☆ 在后台执行命令
☆ 可配置的环境
☆ 高级的命令语言

2. shell的种类

☆ Bourne**shell**(简称sh)
☆ C shell(简称csh)
☆ Korn**shell**(简称ksh)
☆ Bourne Again shell(即bash)

3. shell脚本的建立

一般shell脚本以.sh`` 作为后缀名。

文件头

一种是 :#!/bin/bash<br />另一种是:#!/bin/sh

#!/bin/sh是指此脚本使用/bin/sh来解释执行,#!是特殊的表示符,其后面跟的是此解释此脚本的shell的路径。
其实第一句的#!是对脚本的解释器程序路径,脚本的内容是由解释器解释的,我们可以用各种各样的解释器来写对应的脚本。比如说/bin/csh脚本/bin/perl脚本/bin/awk脚本/bin/sed脚本,/bin/python脚本,甚至/bin/echo等等。

$ cat /etc/shells可以查看系统支持的shell格式,我阿里云服务器默认支持这么多:
/bin/sh 、/bin/bash 、/sbin/nologin
/usr/bin/sh 、/usr/bin/bash 、/usr/sbin/nologin

脚本test.sh内容:
#!/bin/sh
source pcy.sh #pcy.sh并不存在
echo hello
执行./test.sh,屏幕输出为:
./test.sh: line 2: pcy.sh: No such file or directory
由此可见,在#!/bin/sh的情况下,source不成功,不会运行source后面的代码。
修改test.sh脚本的第一行,变为#!/bin/bash,再次执行./test.sh,屏幕输出为:
./test.sh: line 2: pcy.sh: No such file or directory
hello
由此可见,在#!/bin/bash的情况下,虽然source不成功,但是还是运行了source后面的echo语句。
但是紧接着我又试着运行了一下sh ./test.sh,这次屏幕输出为:
./test.sh: line 2: pcy.sh: No such file or directory
表示虽然脚本中指定了#!/bin/bash,但是如果使用sh 方式运行,如果source不成功,也不会运行source后面的代码。

为什么会有这样的区别呢?

junru同学作了解释

  1. sh一般设成bash的软链
    [work@zjm-testing-app46 cy]$ ll /bin/sh
    lrwxrwxrwx 1 root root 4 Nov 13 2006 /bin/sh -> bash

  2. 在一般的linux系统当中(如redhat),使用sh调用执行脚本相当于打开了bash的POSIX标准模式

  3. 也就是说 /bin/sh 相当于 /bin/bash —posix

所以,sh跟bash的区别,实际上就是bash有没有开启posix模式的区别

so,可以预想的是,如果第一行写成#!/bin/bash --posix,那么脚本执行效果跟#!/bin/sh是一样的(遵循posix的特定规范,有可能就包括这样的规范:“当某行代码出错时,不继续往下解释”)

4.执行shell脚本的方式

执行shell脚本的方式基本上有三种:
(1)输入定向到shell脚本
$ bash < 脚本名
(2)以脚本名作为参数
其一般形式是: $ bash 脚本名 [参数]
如果以目前shell(以·表示)执行一个shell脚本,则可以使用如下简便形式:
$ · 脚本名 [参数]
(3)将shell脚本的权限设置为可执行,然后在提示符下直接执行它。
$ chmod a+x ex2
$ PATH=$PATH:.
$ ex2
注意,此时该脚本所在的目录应被包含在命令搜索路径(PATH)中

bash变量的分类、定义形式及引用规则

shell特殊字符

1) 通配符

1.一般通配符
*(星号),它匹配任意字符的0次或多次出现 
?(问号),它匹配任意一个字符
[ ](一对方括号),其中有一个字符组。其作用是匹配该字符组所限定的任何一个字符 
!(惊叹号),如果它紧跟在一对方括号的左方括号([)之后,则表示不在一对方括号中所列出的字符 

2.模式表达式 ——是那些包含一个或多个通配符的字 
*(模式表)——匹配给定模式表中“模式”的0次或多次出现,各模式之间以“|”分开(下同) 
+(模式表)——匹配给定模式表中“模式”的1次或多次出现
?(模式表)——匹配模式表中任何一种“模式”的0次或1次出现
@(模式表)——仅匹配模式表中给定“模式”的一次出现 
!(模式表)——除给定模式表中的一个“模式”之外,可以匹配其他任何东西

2)引号

1.双引号 -->弱引用
由双引号括起来的字符(除$、倒引号(`)和反斜线(\)外)均作为 '普通字符' 对待。

2.单引号 -->强引用
由单引号括起来的字符都作为 '普通字符' 出现

3.倒引号 -->命令替换
倒引号括起来的字符串被shell解释为命令行,在执行时,shell会先执行该命令行,并以它的标准输出结果取代
    整个倒引号部分。
倒引号还可以嵌套使用。但应注意,嵌套使用时内层的倒引号必须用 '反斜线(\)' 将其转义。

3) ?? 输入/输出重定向符

自动打开三个标准文件,即标准输入文件(stdin),标准输出文件(stdout)和标准出错输出文件(stderr)。 
1.输入重定向符   
 一般形式是:命令 < 文件名        
   如:$  score < file1

2.输出重定向符(覆盖重定向,禁止输出到已有文件中)
一般形式是:命令 > 文件名         
   如:$ who > abc

    # 使用    set -C 禁止覆盖
    # 强制覆盖 使用>| 重定向
3.输出附加定向符(追加,在已有文件之后追加新的内容)
一般形式是:命令>>文件名         
   如:$ ps -l >> psfile
输入和输出重新定向可以连在一起使用。例如:
    $ wc  -l < infile > outfile

4.即时文件定向符
即时文件的形式是:
   命令  [参数]<< 标记符
   输入行
    …
   标记符
  注意:标记符要成对出现    ! !  !
例如:
  mail  $1 << !!
  Best  wishes  to  you  on  your  birthday .
  !!

5.与文件描述字有关的重定向
系统为每个进程自动打开三个标准文件(即标准输入、标准输出和错误输出),其文件描述字分别为0,1和2。
标准错误输出也可重定向到一个文件中,其一般形式是:
  命令  2> 文件名
  命令  2>> 文件名
标准输出和标准错误输出可以重定向到同一个文件,一般形式是:
   command  &> file  # 覆盖重定向
   command  &>> file # 追加重定向

等价于下面形式的命令:
   command > file  2>&1 # 错误流&标准流

4) 命令执行操作符

1.顺序执行
在执行时,以分号隔开的各条命令从左到右依次执行
pwd ; who | wc -l ; cd /usr/bin
2.逻辑与
命令1 && 命令2
其功能是,先执行命令1,如果执行成功,才执行命令2;否则,若命令1执行不成功,则不执行命令2。
3.逻辑或
命令1 || 命令2
其功能是,先执行命令1,如果执行不成功,则执行命令2;否则,若命令1执行成功,则不执行命令2。

5) 成组命令

1.{ }形式
以花括号括起来的全部命令可视为语法上的一条命令,出现在管道符的一边。
$ { echo “User Report for date . ”; who ; } | pr
使用花括号时在格式上应注意:左括号 “{ ”后面应有一个空格;右括号“}”之前应有一个分号( ;)
2.( )形式
(echo “Current directory is pwd . “
cd /home/mengqc ; ls -l ;
cp m1 em1 && rm m1
cat em1) | pr

两者的区别

二者存在重要区别:用花括号括起来的成组命令只是在本shell内执行命令表,不产生新的进程;而用圆括号括起来的成组命令是在新的子shell内执行,要建立新的子进程。

pr 分页

打印输出,将较大的文件分割成多个页面,并为每个页面添加标题

变量

自定义变量

1.变量名是以字母或下线符打头的字母、数字和下线符序列,并且大小写字母意义不同。
2. 定义变量并赋值的一般形式是:
变量名=字符串
3.引用变量值 在变量名前面加上一个符号“$”或者前面加“$”并用“{}”包围
如果在赋给变量的值中要含有空格、制表符或换行符,那么,就应该用双引号把这个字符串括起来。
注意“=” 前后不能有空格

#!/sh/bash
# 按照顺序执行
pwd ;  who | wc  -l ;  date;
echo "----------------------------------------"
# 逻辑或条件执行 找不到文件输出提示
cat abc || echo "您输入的文件不存在!"
echo "----------------------------------------"

echo "----------------------------------------"
# 定义变量并引用
dira=/home/gaox
cat ${dira}/abc
echo "----------------------------------------"

各种控制语句的格式、功能及流程

bash中算术运算的使用

bash函数的构成及使用规则

bash中的内置命令