一、基础概念
shell语言是一种在Linux/Unix系统下的脚本语言,它有不同的版本,比如sh, bash, ksh, csh, tcsh. 最常用的是Bash。它是由c编写的,是外层应用于操作系统内核交互的桥梁。同时它是一种弱类型语言,使用变量不需要申明
脚本:简单来说就是一条条的文字命令
-
shell的应用
运维,处理文本类型的数据……
-
shell的优缺点:
- 优点:短小精干(编写的程序能够直接别操作系统执行),可移植性强(具有跨平台性),
- 缺点:不够灵活,执行速度慢(它是解释执行的)
- shell所在位置:
- 在Windows中存在的shell文件以: *.bat 结尾
- 在Linux/Unix中存在的shell文件以:*.sh结尾
二、基本语法
1、Shebang
计算机程序中,shebang指的是出现在文本文件中第一行前的两个字符:#!
作用:指定解释器
- 以
#!/bin/sh
开始,表示程序会使用bash解释器去执行 //与#!/bin/bash等同 - 以
#!/usr/pathon
开始,表示程序会使用pathon解释器去执行 - 以
#!/usr/bin/env
开始,表示程序会自动在平台寻找一种合适的解释器去执行
注意:
- #! 指定的解释器必须要有权限,否则会报错
- #!后面指定的解释器,必须填写绝对路径
- 脚本未指定shebang时,程序会默认被shell解释器去执行
- 如果shebang指定的解释器不是一个可执行程序或者格式不正确,指定的解释程序会被忽视
- 如果直接使用指令(例如: bash text.sh )去执行文件,则shebang会被忽视,它会优先使用指令指定的解释器去执行程序
2、注释
#后面接注释内容
作用:对代码块进行解释说明,让代码更直观,更理解代码的作用
注意:
- 尽量养成爱注释的习惯
- 尽量使用英文注释
- 尽量精简
3、shell脚本的执行方式
- bash text.sh / sh text.sh //脚本未获取权限,或者脚本shebang未指定解释器(推荐使用)
- 使用 绝对/相对 路径执行脚本 //脚本需要获得x权限
- source text.sh / . text.sh //source就等价于.
- bash < text.sh / sh<text.sh
获取x权限(可执行权限):
[ghp@localhost ~]$ chmod +x text.sh
4、常用指令
[ghp@localhost ~]$ echo $HISTSIZE /*查询最大历史指令的数量*/
1000 /*不同版本的Linux操作系统可能查找的历史最大里的历史数量不同*/
[ghp@localhost ~]$ history /*查询历史指令,后可接-c/-r*/
-c 清空历史指令
-r 恢复历史指令
!历史指令id号 /*直接执行历史指令*/
!! /*执行上一次的指令*/
/*还可以使用键盘上的上下箭头去执行历史指令*/
[ghp@localhost ~]$ echo $? /*判断上一条指令是否执行成功*/
0 /*执行成功,输出0*/
127 /*执行不成功,输出127。不能版本可能输出同*/
[ghp@localhost ~]$ cat text.sh /*查看文件内容*/
[ghp@localhost ~]$ pstree /*查看进程树,查看具有哪些进程*/
[ghp@localhost ~]$ set |grep 名字 /*检查当前进程中的shell环境变量*/
[ghp@localhost ~]$ rm -f text.sh /*删除文件*/
[ghp@localhost ~]$ history -cw /*清除历史指令*/
[ghp@localhost ~]$ su
[ghp@localhost ~]$ su -
su 和 su - 的区别
set 输出所有变量
declare 输出所有变量
env 只显示全局变量
export 显示和设置环境变量值
ctrl+shift+t 开启两个超级终端窗口,两个窗口是并行的
ls /bin 显示所有命令
mkdir 创建一个新的文件夹
>#是定向输出文件,如果文件不存在,就创建文件;如果文件存在,会覆盖原有文件;一般我们备份清理日志文件的时候,就是这种方法:先备份日志,再用>,将日志文件清空(文件大小变成0字节);
>>#将输出内容追加到目标文件中。如果文件不存在,就创建文件;如果文件存在,则将新的内容追加到那个文件的末尾,该文件中的原有内容不受影响。
使用技巧:
-
文件路径和命令可直接用tab键补全
-
Ctrl+a 转到行首
Ctrl+e 转到行尾
Ctrl+w 剪切光标前一个单词位
ctrl+k 剪切光标后所有字符
ctrl+u 剪切光标前所有字符Ctrl + l 清屏
5、变量
-
变量的使用无需申明,变量赋值和其他语言一样,调用变量需要在变量前添加$变量名
[ghp@localhost ~]$ name="张三" /*变量和等于号之间不能有空格*/ [ghp@localhost ~]$ echo $name 张三
注意:
- 变量只是被临时存储,程序重启或者切换,该变量就失效了
- 变量名的使用要见名知义
- 变量的命名只能包含数字、字母、下划线。不能以数字开头
- 严格区分大小写
- 环境变量和常量字母全部大写
- 变量输出值需要在前面加 符 号 , 变 量 间 赋 值 也 需 要 加 符号,变量间赋值也需要加 符号,变量间赋值也需要加
-
变量的作用域参考c语言和Java语言,规则一样
-
引号和单引号区别:
- 单引号变量不识别特殊语法
- 双引号变量识别特殊语法
-
父子shell面试题详答
- 每次调用bash/sh解释器执行脚本,都开启一个新的子进程,改变的是新的子进程中变量的值
- 调用source/. 执行脚本,让脚本再当前进程中执行,未开启新进程,改变变量的值能够影响到当前进程中的变量
[ghp@localhost ~]$ naem=ghp /*在当前进程中对name变量赋值*/
[ghp@localhost ~]$ echo $name /*输出当前进程中name的值*/
ghp
[ghp@localhost ~]$ touch name.sh /*创建一个shell文件*/
[ghp@localhost ~]$ gedit name.sh /*打开创建的shell文件,对name重新赋值:name=ghp1*/
[ghp@localhost ~]$ echo $name /*因为没有对shell文件进行编译,所以输出的还是先前的name值*/
ghp
[ghp@localhost ~]$ source name.sh /*执行创建的shell文件,改变了当前进程的name变量*/
[ghp@localhost ~]$ echo $name
ghp1
[ghp@localhost ~]$ sh name.sh /*用bash解释器执行shell脚本,创建了一个子进程*/
[ghp@localhost ~]$ name=ghp2 /*改变的是子进程中的name值*/
[ghp@localhost ~]$ echo $name
ghp2
[ghp@localhost ~]$ source name.sh /*用source执行脚本,重新回归父进程*/
[ghp@localhost ~]$ echo $name
ghp1
[ghp@localhost ~]$ sh name.sh /*再次使用bash执行脚本,但是未进行赋值,所以name值不变*/
[ghp@localhost ~]$ echo $name
ghp1
[ghp@localhost ~]$ gedit name.sh /*打开创建的shell文件,对name重新赋值:name=ghp3*/
[ghp@localhost ~]$ sh name.sh /*用bash执行脚本,开启新进程,改变的是新进程中的变量值,并未改变当前进程中的变量值*/
[ghp@localhost ~]$ echo $name
ghp1
ghp@localhost ~]$ source name.sh
ghp@localhost ~]$ echo $name
ghp3
6、算术运算符和算术运算命令
运算符大部分和c相同(例如:加减乘除,取余,加加,减减……),特别有乘方:2**3=8 等价于2^3,shell脚本中不能直接再命令窗口中进行数字之间的运算,需要使用一些运算符或运算命令,输出值需要加$
- 常用算术运算命令:
运算命令 | 作用 |
---|---|
(()) | 用于整数运算(例如:判断,赋值,四则运算,乘方),效率特别高 |
let | 让变量之间能够直接进行运算(不需要使用$) |
expr | 可用于整数运算(运算符左右要有空格),判断,赋值。字符串匹配 |
bc | Linux中的一个计算器 |
[] | 用于整数运算,和(())类似(注意前后要空格) |
awk | 用于整数、小数的运算 |
declare | -i参数,可以定义整型变量进行运算 |
[ghp@localhost ~]$ echo $((2>3||2<3))
1 //判断未真
[ghp@localhost ~]$ echo $((2>3&&2<3))
0 //判断为假
[ghp@localhost ~]$ ((i=i+1)) 等价于 i=((i+1)) 等价于 ((++i))
[ghp@localhost shell_project]$ expr 2 + 3 #直接运算
5
[ghp@localhost shell_project]$ n=2 #变量间运算需要加$
[ghp@localhost shell_project]$ expr $n + 3
[ghp@localhost shell_project]$ echo $n
5
[ghp@localhost shell_project]$ n=`expr $n +5` #赋值
[ghp@localhost shell_project]$ echo $n
10
expr详情 bc详情(其中除法运算,只能大数除小数,遇到结果为无限小数或小数相除只保留一位)
注意:函数执行需要调用函数名,函数名不需要括号,且函数名不能和末尾大括号在同一行
[ghp@localhost ~]$ cat test.sh
#!/bin/bash
f(){
echo "hello shell!"
} #f不能写在这里,会报错
f
[ghp@localhost ~]$
[ghp@localhost ~]$ sh test.sh
hell shell!
7、函数和符号
通过各种shell命令之间的组合,构成一个函数体,专门用来解决某一个或多个问题。函数的使用可以是shell程序更具有可读性。
函数命名要就简明和。先定义再调用,调用直接写函数名即可。
#标准函数定义
function 函数名(){} #使用了function关键字()可以省略,没有function时必须要有()
-
定义函数和执行函数分开再两个文件
#使用source执行脚本 [ghp@localhost ~]$ ls my_function shell_project 公共 模板 视频 图片 文档 下载 音乐 桌面 [ghp@localhost ~]$ source ~/my_function/f.sh #在my_function文件中创建了一个函数,在父进程中调用 [ghp@localhost ~]$ f sucessfully!
-
函数的参数
-
$1、$2、$3……$9、${10}……代表传递给脚本或函数的第1~n个参数;$0表示当前脚本的文件名
-
$?判断上个命令执行是否成功,或上一个函数的返回值 就近原则
-
$$ 代表当前进程的id
-
$# 代表添加的参数个数
-
$@ 和 $* 代表所有的参数。不加引号,输出它们,都是 //?
……
-