基本语法
变量
变量的使用
生成变量时必须注意, 变量 = 前后不能有空格.
读取变量时需要在变量前加 $ 美元符, 或者 ${}美元符加花括号, 使用花括号为了帮助解释器识别变量的边界.
示例:
- name="DonYau"
- echo $name
- echo ${
- name
- }
与此同时可以通过 ${#name}获取变量的长度
read 获取用户的输入
read 命令从标准输入 (键盘) 或另一个文件描述符中接受输入. 在收到输入后, read 命令 会将数据放进一个变量. 使用 read 时, 可以设置 - t n 来设置一个定时器, 当计时器过期后, read 会返回一个非零退出状态码
例如:
- echo -n "Enter your age:"
- read age
数组
格式: names=(value1 ... valuen) 数组元素之类采用空格隔离
可以使用索引值对数组进行赋值:
- names[0]=name
- names[1]=age
读取数组的某个值:
- echo ${
- names[0]
- }
- index=1
- echo ${
- name[$index]
- }
显示整个数组的值:
- echo ${
- name[*]
- }
- echo ${
- name[@]
- }
删除数组中的某个值:
- unset name[1]
- // 删除整个数组
- unset name[*]
获取数组的长度
- echo ${
- #name[*]
- }
- echo ${
- #name[@]
- }
输出数组的所有值
- echo ${
- name[*]
- }
- echo ${
- name[@]
- }
test 命令
test 命令可以判断三类条件:
数值比较
字符串比较
文件比较
数值比较
运算符 | 含义 |
---|---|
-eq | 等于 |
-ne | 不等于 |
-gt | 大于 |
-lt | 小于 |
-ge | 大于或者等于 |
-le | 小于或者等于 |
例如:
- value1=10
- if [ $value1 -gt 5 ];then
- echo "$value1 大于 5"
- fi
字符串比较
运算符 | 含义 |
---|---|
str1 = str2 | 检查 str1 是否和 str2 相同 |
str1 != str2 | 检查 str1 是否和 str2 不相同 |
str1 < str2 | 检查 str1 是否比 str2 小 |
str1 > str2 | 检查 str1 是否和 str2 大 |
-n | 检查 str1 的长度是否非 0 |
-z | 检查 str1 的长度是否为 0 |
注意: 在字符串使用比较符时, 大于号和小于号必须转义, 否则 shell 会把它们当作重定向符号
例如:
- value1=a
- value2=b
- if [ $value1 = $value2 ];then
- echo "两个值是否相等"
- fi
- if [ $value1 \> $value2 ];then
- echo "value1 大于 values"
- fi
文件比较
运算符 | 含义 |
---|---|
-d | 文件是否存在,且为目录 |
-e | 文件是否存在 |
-f | 文件是否存在,且为普通文件 |
-r | 文件是否可以读 |
-s | 文件存在,且大于 0 |
-w | 文件存在且可写 |
-x | 文件存在且可执行 |
复合条件
- [ condition1 ] && [ condition2 ]
- [ condition1 ] || [ condition2 ]
括号的使用
双括号
双括号允许在比较过程中使用高级数学表达式
例如:
- value=10
- if (( $value ** 2> 19 )); then
- echo "大于 19"
- fi
双方括号
双方括号里的 expression 使用了 test 命令中采用的标准字符串比较. 但它提供了 test 命令未提供的另一个特性 -- 模式匹配
\\ 使用了双等号 ==, 双等号将右边的字符串 (*e*) 视为一个模式, 并应用模式匹配规则
- value="shell find"
- if [[ $value == *e* ]]; then
- echo "符合"
- fi
使用结构化命令
base shell 的 if 语句会运行 if 后面的命令, 如果该命令的退出状态码是 0, 这命令成功运行, 位于 then 部分的命令就会被执行. 如果退出状态码是其他值, then 部分的命令就不会被执行.
if-then
格式:
- if command
- then
- command
- fi
if-then-else
格式:
- if command
- then
- commands
- else
- commands
- fi
- if-then-elif
- if command
- then
- command
- elif command
- then command
- command
- fi
case
例如:
- value=2
- case $value in
- 1 | 2)
- echo "1 或者 2";;
- 3)
- echo "3";;
- *)
- echo "other";;
- esac
for
格式:
- for var in list
- do
- commands
- done
默认情况下, base shell 会将空格, 制表符, 换行符当作字段分隔符.
更改字段分隔符
\\ 定义单个 IFS 字符
IFS=$'\n'
\\ 定义多个 IFS 字符
IFS=$'\n':;
while
格式:
- while test command
- do
- other commands
- done
循环的输出
在 shell 脚本中, 可以对循环的输出使用管道或进行重定向. 这可以通过在 done 命令之后添加一个处理命令来实现.
例如:
- for (( i = 1; i <10; i++ ))
- do
- echo "The number is $a"
- done> test.txt
函数
函数定义
在 shell 中使用函数时, 必须先定义函数, 否则会报错误. 如果重新定义了函数, 新定义的函数会覆盖原函数, 并且不会产生任何错误.
格式:
- // 第一种
- function name {
- commands
- }
- // 第二种
- name() {
- commands
- }
函数变量
函数内部使用的任何变量都可以被声明成局部变量. 要实现这 一点, 只要在变量声明的前面加上 local 关键字, 该关键字保证了变量只局限在该函数中. 倘若不使用 local 关键字, 即使是在函数中申明的变量, 在外部也可以访问.
函数参数
函数可以使用标准的参数环境变量来表示命令行上传给函数的参数. 在函数内部, 通过 $# 获取参数的个数,$0 获取函数的名称,$1 获取第一个参数,$2 获取第二个参数, 以此类推
例如:
- function log() {
- echo $0
- echo $#
- echo $1
- echo $2
- }
- log a 2
将数组变量当作单个参数传递的话, 将不会起作用, 函数只会取数组变量的第一个值. 因此, 可以将该数组变量的值分解成单个的值, 然后将这些值作为函数参数使用. 在函数内部, 可以将所有的参数重新组合成一个新的变量.
例如:
- function log() {
- local a
- a=$(echo "$@")
- echo ${a[*]}
- }
- array=(1 2 3 4 5)
- log ${array[*]}
函数返回值
每个函数都有返回状态码. 默认情况下, 函数的退出状态码是函数中最后一条命令的返回退出状态码. 可以使用 $? 来确定函数的退出状态码. 不建议使用默认的函数状态码, 因为最后一条命令运行成功不代表中间的命令都能运行成功.
函数的返回值必须小于 255, 任何大于 256 的值都会产生一个错误的值.
介于以上情况, 采用另外一种输出方式, 例如:
- function log() {
- echo 300
- }
- result=$(log)
- echo $result
若要从函数中返回数组时, 可以使用 echo 按正确的顺序输出单个数组值.
例如:
- function log() {
- local a=(1 2 3 4 5)
- echo ${a[*]}
- }
- result=$(log)
- echo $result
基本操作
echo 打印指令
输出命令一般有三个格式:
直接输出
单引号概括输出
双引号概括输出
单引号内无法读取变量的值, 例如
- age=18
- echo '$age'
- $age
当双引号概括输出时, 若读取变量后直接拼接字符串, 需要使用 ${}方式读取变量, 例如:
- age=18
- echo "$age 岁"
- ??
- echo "${age}岁"
18 岁
默认情况下, echo 在每次调用后会添加一个换行符, 同时也可以使用 - n 忽略行号符, 例如:
- echo "male";echo "female"
- male
- female
- echo -n "male";echo "female"
- malefemale
装逼模式, 彩色输出
- // 输出加粗红色字体
- echo -e "\033[01;31m 颜色字体 \ 033[0m"
颜色字体
- // /03[4m 下划线
- // /033[5m 闪烁
上面输出格式中 01 表示加粗, 31 表示是红色, 后面 \ 033[0m 表示恢复所有的属性为原来的默认值
字体色号 | 颜色 | 背景色号 | 颜色 |
---|---|---|---|
30 | 黑色 | 40 | 黑色 |
31 | 红色 | 41 | 红色 |
32 | 绿色 | 42 | 绿色 |
33 | 黄色 | 43 | 黄色 |
34 | 蓝色 | 44 | 蓝色 |
35 | 紫色 | 45 | 紫色 |
36 | 深绿色 | 46 | 深绿色 |
37 | 白色 | 47 | 白色 |
cd 遍历目录
cd 命令可接受相对路径和绝对路径
ls 显示当前目录的文件和文件夹
ls 命令支持定义过滤器, 通过过滤器决定输出哪些文件或目录.
可以使用简单匹配字符:
? 代表一个字符
* 代表一个星号
[]代表元字符或者 [a-c] 代表范围
[!a]使用感叹号将不需要的内容排除在外
在使用参数过程中, 可以组合参数使用, 例如:
- ls -aF
- ./ .putty/
- ../ .sogouinput/
- .CFUserTextEncoding .SSH/
- .DS_Store .templateengine/
- .IdentityService/ .viminfo
- .ServiceHub/ .yarnrc
参数 | 作用 |
---|---|
-F | 区分文件与文件夹,文件夹后面会带 / 斜杠 |
-a | 显示隐藏文件 |
-R | 递归显示 |
-l | 显示文件的相关信息 |
touch 创建文件
例如:
touch data.txt
cp 复制文件
格式: cp [file1] [file2]
格式: cp [file1] [file2] directory 该命令必须在 directory 存在的情况下使用
注意当使用 - R 拷贝文件夹时, 如果 file2 文件夹已经存在会在 file2 在创建 file1 的递归文件
当执行复制时, 如果 file2 文件已经存在, 则会覆盖 file2 的文件
参数 | 含义 |
---|---|
-i | 如果 file2 存在时,询问是否覆盖 |
-R | 递归复制整个目录 |
-f | 如果对象已经存在则先删除 |
mv 移动或重命名
格式: mv [file1] [file2]
格式: mv [file1] [file2] directory
参数 | 含义 |
---|---|
-i | 如果 file2 存在时,询问是否覆盖 |
-R | 递归复制整个目录 |
rm 删除文件
格式: rm [file]
格式: rm -r directory
支持使用通配符成组的删除文件
参数 | 含义 |
---|---|
-i | 询问是否删除 |
-f | 强制删除 |
-r -R | 直接删除普通文件,如果是路径就会一次删除下一级路径和文件 |
mkdir 创建目录 rmdir 删除目录
mkdir
格式: mkdir directory
参数 | 含义 |
---|---|
-p | 创建路径中缺失的父目录 |
rmdir
格式: rmdir directory
该命令很少使用, 因为该命令只能删除空目录
参数 | 含义 |
---|---|
-p | 创建路径中缺失的父目录 |
file 查看文件类型
格式: file [file]
cat 查看文件内容
格式: cat [file]
参数 | 含义 |
---|---|
-n | 给所有的行加上行号 |
-n | 给只有文件的行加上行号 |
find 文件查找
格式: find base_path
列出当前目录及子目录下的所有文件和文件夹
根据文件名或正则表达式匹配
格式: find base_path -name
例如:
- // 查找当前目录下以 ".txt" 结尾的文件
- find . -name "*.txt"
- // 查找当前目录下以 ".txt" 或 ".PDF" 结尾并忽略大小写的文件,"\(\)" 是指将括号内的内容视为一个整体
- find . \( -iname "*.txt" -o -iname "*.PDF" \)
根据文件路径匹配
将文件路径作为一个整体进行匹配
格式: find base_path -path
例如:
find . -path "*txt"
使用否定参数
例如:
- // 查找当前目录下不以 ".txt" 结尾的文件
- find . ! -name "*.txt"
基于目录的深度搜索
格式:
-maxdepth num 最大深度 num
-mindepth num 最小深度 num
例如:
- // 查找当前目录及子目录下以 ".txt" 结尾的文件
- find . -maxdepth 2 -name "*.txt"
基于文件类型搜索
-type 对文件类型进行过滤
-type f 普通文件 -type d 目录
基于文件大小搜索
例如:
- // 搜索大于 2k 的文件
- find . -type f -size +2k
删除匹配的文件
例如:
- // 删除大于 2k 的文件
- find . -type f -size +2k -delete
跳过特定的目录
例如:
find . \( -name ".Git" -prune \) -o \( -type f -print \)
gzip 压缩文件 gunzip 解压文件
gzip
格式: gzip [file]
gunzip
格式: gunzip [file]
重定向与管道
简介
重定向与管道的操作过程如图:
基本命令行程序都能在屏幕上显示输出结果, 称之为标准输出, 文件的描述符数值为 1. 同时我们也可以利用标准输出重定向保存为文件, 将文件内容指定为命令的输入
输出重定向
格式: ls> [file]
>操作会将原有的内容覆盖, 如果我们需要添加内容则使用>>
输入重定向
格式: command <[file]
文件描述符
标准 I/OW 文件描述符类型如下:
I/O | 描述符 |
---|---|
输入 | 0 |
输出 | 1 |
错误 | 2 |
使用方法:
- // 将错误输出到 stderr.tet 正常输出到 stdout.txt
- ls + 2>stderr.txt 1>stdout.txt
管道
通常通过组合指令, 连续使用指令的方法执行多个指令, 此时就可以使用 | 字符连接两个指令. 这就是管道, 表示前一命令的结果值成为下一个命令的输入.
格式: ls -l | Less
高级语法
grep
基本使用
grep 命令是 UNIX 中用于搜索的大师级工具, 能够接受正则表达式和通配符.
格式: grep [格式] [文件]
grep 可以多个文件进行搜索, 例如: grep [格式] [文件] [文件] [文件] ...
选项 | 含义 |
---|---|
-E | 使用扩展正则表达式 |
-P | 使用 Perl 正则表达式 |
-o | 只输出文件中匹配到文本的部分 |
-v | 输出匹配行之外的所有行 |
-c | 统计文件或者文本中匹配的行数 |
-l | 搜索多个文件,并找出匹配文本位于哪个文件中 |
-R | 递归搜索文件 |
-i | 忽略大小写 |
-e | 匹配多个样式 |
-A | 输出匹配结果之后的几行 |
-B | 输出匹配结果之前的几行 |
-C | 输出匹配结果之前和之后的几行 |
例如:
- cat data.txt
- 112233444
- a1a1a1a1a1
- bring1
- pipei
- 44454321
- grep -E "^1" data.txt
- 112233444
- grep -E -o "^b" data.txt
- b
- grep -v "^b" data.txt
- 112233444
- a1a1a1a1a1
- pipei
- 44454321
- aaa12122
- grep -e "^b" -e "4$" data.txt
- 112233444
- bring1
- grep -E "^b.+1$" data.txt -A 1
- bring1
- pipei
- grep -E "^b.+1$" data.txt -B 1
- a1a1a1a1a1
- bring1
- grep -E -c "4$" data.txt
- 1
- // 在递归搜索所有的 `.c` 和 `.cpp` 文件
- grep "title" dir2 -R --include *.{
- c,cpp
- }
- // 在搜索中排除所有的 readme 文件
- grep "title" dir -R --excluds "readme"
grep 中的静默输出
在某些情况下, 只需要知道一个文件是否包含指定的文本, 因此通过设置 grep 中的 - q 执行一个可以返回真假的条件测试. 在静默模式中, grep 命令不会向标准输入打印任何输出, 仅仅是运行命令, 根据命令执行成功与否返回退出的状态.
例如:
- grep -q "test" file
- if [ $? -eq 0 ];then
- echo "包含 test"
- fi
egrep
egrep 是 grep 的扩展, 可以使用其他正则表达式的元字符集, 相当于 grep -E 模式.
持续更新.....
来源: https://juejin.im/post/5bafb706e51d450e8f5fb7de