Shell的作用:
- 解释执行用户输入的命令或程序等
- 用户输入一条命令,shell就解释一条
- 键盘输入命令,Linux就给出响应的方式,称为交互式
外层应用程序 -> shell解释器 -> 操作系统核心 -> 机器硬件
shell脚本:
windows中存在".bat"批处理脚本
linux 中常用".sh"脚本文件
SheBang:
计算机程序中,shebang指的是出现在文本文件第一行前两个字符: #!
在Unix系统中,程序会分析shebang后面的内容,作为解释器的指令,例如:
- 以 #! /bin/bash 或 #! /bin/sh 开头的文件,程序在执行的时候会调用/bin/sh,也就是bash解释器
- 以 #! /usr/bin/python 开头的文件,代表指定python解释器执行
- 以 #! /usr/bin/env 开头的文件,是一种在不同平台上都能正确找到解释器的办法
sh和bash一样的。
执行shell
- sh hello.sh
- hello.sh(PATH里没有)
- ./hello.sh(权限不够,添加权限: chmod +x hello.sh)
- /bin/bash ./hello.sh 或 /bin/sh ./hello.sh
bash/sh ,文件本身没权限执行,没x权限,则使用的方法,或脚本未指定shebang,重点推荐的方法
使用 绝对/相对 路径执行脚本,需要文件含有x权限
source script.sh / . script.sh 代表当前会话执行,bash/sh 生成一个子sh执行
少见的用法:sh < script.sh
定义
shell语言定义的变量,数据类型默认都是字符串,弱类型语言
作用域
- 环境变量(全局变量):eg:$PATH
- 局部变量,针对 shell函数 或 shell脚本 的参数
脚本:
特殊状态
# 上一次命令执行状态返回值, 0正确,非0失败
$?
# 当前shell脚本的进程号
$$
# 上一次后台进程的PID
$!
# 上次执行的命令,最后一个参数
$_
# 获取参数个数
$#
# 获取参数第几个
#1 #2 #3 ...
# 执行脚本名称
#0
变量
#支持的shell
cat /etc/shells
#定义变量,变量和值直接不能有空格,只能包括数字、字母、下划线,不能以数字开头,严格区分大小写
name="hello"
# '' 不识别特殊符号,""识别特殊符号,""里变量的{}不能省略
nane1='${name}' # '${name}'
name2="${name}" # hello
echo ${name} = echo $name
# 生成子shell,退出 exit
sh
#上一条命令是否成功: 0代表成功,否则失败
$?
历史命令
# 查看历史命令
history
#保留用户命令的个数
echo $HISTSIZE
#查看历史文件
echo $HISTFILE #/root/.bash_history
cat /root/.bash_history
#清空历史命令
history -c
#恢复历史命令
history -r
#执行命令
!550
#执行上一个命令
!!
简单执行
[ $# -lt 2 ] && {
echo "<2个参数"
exit 119
}
echo ">=2个参数"
# 参数个数小于2个输出 "<2个参数" ,否则输出">=2个参数"
bash一些基础的内置命令
echo
-n do not append a newline
不换行输出
-e enable interpretation of the following backslash escapes
启用下划线转义字符: 能够识别特殊字符
-E explicitly suppress interpretation of backslash escapes
不启用反斜线转义的解释(默认)
使用选项-e时,如果在字符串中键入以下字符,程序不用将它当一般字符输出,而是使用转义功能
\a 发出一个警告
\b 删除前一个字符
\c 最后不加换行符,并抑制字符后输出
\f 换行,但光标仍停留原来的位置
\n 换行,光标移到行首
\r 光标移到行首,但不换行
\t 水平制表符
\v 垂直制表符
\\ 插入\字符
\0nnn 插入nnn(八进制)所代表的ASCII字符,nnn代表0-3位八进制数字
\xHH 插入HH(十六进制)所代表的ASCII字符,HH代表1-2位十六进制数字
[root@192_168_52_88 test]# echo "Today is sunny"
Today is sunny
[root@192_168_52_88 test]# echo -e "Today \bis \bsunny"
Todayissunny
[root@192_168_52_88 test]# echo -e "Today is \csunny"
#Today is [root@192_168_52_88 test]#
[root@192_168_52_88 test]# echo -e "Today is sunny\nlo"
Today is sunny
lo
[root@192_168_52_88 test]# echo -e "Today \ris sunny"
is sunny
#回车,光标移到首位,但不换行
eval
exec
export
read
shift
字符串
截取字符串:
# 截取左边的
% 截取右边的字符串
# 左边匹配第一个;## 右边匹配第一个
% 右边匹配第一个;%% 左边匹配第一个
file=/dir1/dir2/dir3/my.file.txt
# 长度
${#file}
# 删掉第一个/及其左边的字符串:dir1/dir2/dir3/my.file.txt
${file#*/}
# 删掉最后一个/及其左边的字符串:my.file.txt
${file##*/}
# 删掉第一个.及其左边的字符串:file.txt
${file#*.}
# 删掉最后一个.及其左边的字符串:txt
${file##*.}
# 删掉最后一个/及其右边的字符串:/dir1/dir2/dir3
${file%/*}
# 删掉第一个/及其右边的字符串:(空值)
${file%%/*}
# 删掉最后一个.及其右边的字符串:/dir1/dir2/dir3/my.file
${file%.*}
# 删掉第一个.及其右边的字符串:/dir1/dir2/dir3/my
${file%%.*}
# 对比,少一个/ 引起是否匹配问题
# /dir2/dir3/my.file.txt
echo ${file#/d*1}
# /dir1/dir2/dir3/my.file.txt
echo ${file#d*1}
# ${var:start:length}
# 提取最左边的5个字节:/dir1
${file:0:5}
# 提取最后5个字节(注意-5前有空格):e.txt
${file: -5}
# 去掉头部5字节、尾部5个字节:/dir2/dir3/my.fil
${file:5: -5}
# 先取最后11个字节,再去掉最后4个字节:my.file
${file: -11: -4}
字符串替换,不写入原变量
# ${var/ / } ${var// / }
# 将第一个dir替换为path:/path1/dir2/dir3/my.file.txt
${file/dir/path}
# 将全部dir替换为path:/path1/path2/path3/my.file.txt
${file//dir/path}