知行合一
Github
顺翔的技术驿站
顺翔的技术驿站
  • README
  • ABOUTME
  • Computer Science
    • 数据结构与算法
      • 位运算以及位图
      • 随机数
      • 递归
      • 经典排序算法
      • 经典查找算法
      • 数组和动态数组
      • 链表
      • 栈和队列
      • 树
      • 哈希表
    • 计算机网络
      • 物理层
      • 数据链路层
      • 网络层
        • TCP
      • 运输层
      • 应用层
      • HTTP
        • HTTPS的原理
        • DNS详解
        • file协议
        • 邮件协议
    • 设计模式
      • 单例模式
      • 建造者模式
      • 原型模式
      • 工厂模式
      • 享元模式
      • 代理模式
      • 装饰者模式
      • 桥接模式
      • 适配器模式
      • 外观模式
      • 组合模式
      • 事件驱动
      • 有限状态机
      • 备忘录模式
      • 模板方法模式
      • 策略模式
      • 迭代器模式
      • 命令模式
      • 解释器模式
    • 加密与解密
      • 数字证书原理
      • cfssl
  • Programming Language
    • 编程语言学习要素
    • Java
      • 集合
        • List
          • ArrayList
          • Vector
          • Stack
          • LinkedList
        • Iterator
        • Set
          • HashSet
          • TreeSet
        • Map
          • HashMap
          • HashTable
          • TreeMap
          • LinkedHashMap
      • 常用API
        • 日期时间处理
        • System
        • Random
        • Arrays
        • Scanner
        • 格式化输出
      • java特性
        • java5特性
        • java8特性
        • java9特性
        • java10特性
        • java11特性
      • 并发编程
        • 线程基础
        • 线程同步:synchronized及其原理
        • 线程同步: volatile
        • 锁机制
        • 锁的分类与对应的Java实现
        • JUC:同步辅助类
        • JUC: AtomicXXX
        • 线程池
        • ThreadLocal详解
      • 测试
        • 使用JMH进行基准测试
      • JVM
        • 强引用、软引用、弱引用、虚引用
        • jvm内存模型
        • jvm优化
        • GC算法与回收器
        • 静态绑定与动态绑定
      • ORM
        • Mybatis
          • IBatis常用操作
      • Web编程
        • Servlet详解(一)
        • Servlet详解(二):request和response对象
        • Servlet详解(三):会话技术与Cookie
        • JSP详解(一):页面构成、EL表达式
        • JSP详解(二):九大内置对象
        • JavaWeb的编码问题
        • Thymeleaf
      • Velocity
      • Java日志框架总结
      • Spring
        • SpringIOC
        • SpringMVC
        • SpringBoot源码
      • 其他
        • Apache Commons Lang使用总结
        • 使用FtpClient进行ftp操作
        • Java PDF操作总结
        • Java使用zip4j进行文件压缩
        • Java解析Excel总结
    • JVM Language
      • Groovy
      • Scala
    • Kotlin
      • 变量和常量
      • 数据类型
        • 基本数据类型
        • 容器类型
        • 函数类型
        • null和null安全
      • 流程控制
      • 包
      • 面向对象
    • Golang
      • 关键字与标识符
      • 变量和常量
      • 数据类型
      • 函数
      • 常用API
        • 时间日期处理
        • 字符串操作
        • 正则表达式
      • 控制语句
      • 包package
      • 面向对象
      • 错误处理
      • 命令行编程
        • Cobra
      • 文件操作
      • 测试
      • 并发编程
        • sync包详解
      • 数据格式与编码
        • 使用encoding包操作xml
        • 使用encoding包操作json
        • 使用magiconair操作properties
        • 使用go-ini操作ini
      • 反射
      • Build Tools
        • Go Module
        • Go Vendor
      • 日志框架
        • zap日志框架
      • Web编程
        • Gin
    • JavaScript
      • 数据类型
      • ECMAScript
        • ECMAScript6
      • NodeJS
    • TypeScript
      • 变量和常量
      • 数据类型
      • 函数
      • 面向对象
      • 泛型
      • Build Tools
        • tsc编译
        • 与webpack整合
    • Python
      • BuildTools
        • requirements.txt
        • Ananconda
    • Swift
      • 变量和常量
    • Script Language
      • Regex
      • BAT
      • Shell
    • Markup Language
      • Markdown
      • Yaml
  • Build Tools
    • CMake
    • Maven
      • 搭建Nexus私服
      • maven使用场景
    • Gradle
  • Version Control
    • Git
      • Git工作流
      • Git分支管理
      • Git Stash
      • Git Commit Message规范
      • .gitttributes文件
    • SVN
  • Distributed
    • 分布式基础理论
      • 互联网架构演变
      • 架构设计思想AKF拆分原则
      • CAP理论
      • BASE理论
    • 一致性
      • 一致性模型
      • 共识算法
        • Paxos
        • Raft
        • ZAB
      • 复制
        • 主从复制
        • Quorum机制
        • Nacos Distro协议
      • 缓存一致性
        • 双写一致性
        • 多级缓存一致性
    • 事务一致性
      • Seata
      • 本地消息表实现方案
      • 关于dpad的事务问题的分析
    • IO
    • RPC协议
    • 序列化
    • Session共享
    • 分布式协调
      • Zookeeper
        • zk集群4节点搭建
    • 服务治理
      • Dubbo分布式治理
    • 分布式ID
      • 分布式ID生成策略总结
    • 分布式锁
    • 应用服务器
      • Tomcat
    • Web服务器
      • Nginx
        • Nginx的基本配置
        • ab接口压力测试工具
        • nginx模块
        • 随机访问页面
        • 替换响应内容
        • 请求限制
        • 访问控制
        • 状态监测
        • nginx应用场景
        • 代理服务
        • 负载均衡
        • 缓存
        • 静态资源服务器和动静分离
        • 附录
      • Kong
    • 缓存中间件
      • Caffeine
      • memcached
      • Redis
        • Centos下安装Redis
        • RatHat下安装Redis
    • 数据库中间件
      • ShardingSphere
      • MyCat2
    • 消息中间件
      • Kafka
      • RocketMQ
  • Microservices
    • 服务发现
      • Nacos注册中心
      • Consul
    • 配置中心
      • Apollo
    • 消息总线
    • 客户端负载均衡
    • 熔断器
    • 服务网关
    • 链路追踪
      • Skywalking
  • Domain-Specific
    • Auth
      • 有关权限设计的思考
      • 认证方式
      • JWT
    • 任务调度
      • QuartzScheduler
      • Elastic-Job
      • XXL-Job
      • PowerJob
    • 工作流
      • BPM
      • Activiti
      • Flowable
    • 规则引擎
      • Drools
  • Architect
    • DDD领域驱动设计
      • 三层架构设计
      • 四层架构设计
    • Cola
    • 代码设计与代码重构
      • 重构改变既有代码设计
      • 枚举规范化
      • 接口幂等
      • 限流
      • 历史与版本
      • 逻辑删除和唯一索引
      • 业务对象设计
    • 单元测试
      • SpringBoot单元测试实践
    • 项目管理
    • APM
      • SkyWalking
      • Arthas
    • 性能优化
      • 接口性能优化
    • 系统设计
      • 流程中台
      • 短信中台
      • 权限中台
        • 智电运维平台组织架构改造二期
  • Database
    • Oracle
      • Docker下安装oracle11g
    • IBM DB2
    • Mysql
      • 安装Mysql
      • 用户与权限管理
      • MySQL的逻辑架构
      • 存储引擎
      • 索引详解
      • MySql的列类型
      • MySql中表和列的设计
      • MySql的SQL详解
      • 锁机制
      • 事务
      • Mysql函数总结
      • MySql存储过程详解
      • MySql触发器详解
      • Mysql视图详解
      • Mysql中Sql语句的执行顺序
      • 配置MySql主从和读写分离
      • MySql的备份策略
      • MySql分库分表解决方案
      • MySql优化总结
      • MySQL实战调优
        • schema与数据类型优化
    • Mongo
  • File System
    • README
    • HDFS
    • FastDFS
    • MinIO
  • Linux
    • 常用的Linux命令
    • vim
    • Linux磁盘管理
    • Linux系统编程
    • RedHat
      • rpm包管理器具体用法
    • Ubuntu
      • Ubuntu下录制屏幕并做成gif图片
      • Ubuntu20.05LiveServe版安装
  • DevOps
    • VM
      • 新建一个新的Linux虚拟机需要配置的东西
      • VMware桥接模式配置centos
      • VMwareFusion配置Nat静态IP
    • Ansible
    • Container
      • Docker
        • Dockerfile详解
        • DockerCompose详解
      • Containerd
    • Kubernetes
      • 安装k8s
        • 使用Minikube安装k8s
        • centos7.x下使用kubeadm安装k8s1.21
        • ubuntu20下使用kubeadm安装k8s1.21
        • centos7.x下使用二进制方式安装k8s1.20
        • 使用DockerDesktop安装K8s(适用M1芯片)
      • 切换容器引擎
      • 使用k8s部署项目的流程
      • 集群维护-备份升级排错
    • Gitlab
      • GitlabCI/CD
    • CI/CD
      • ArgoCD
  • Big-Data
    • Hadoop
    • MapReduce
    • HDFS
  • Front-End
    • Android
      • Log的使用、自定义Log工具类
      • Android倒计时功能实现
      • 解决ViewDrawableLeft左侧图片大小不可控的问题
      • AndroidSQLite基本用法
      • View的生命周期
      • 工具类
      • WebView详解
      • ViewTreeObserver类监听ViewTree
      • 在onCreate中获取控件的宽高等信息的几种方法
      • View的foreground属性
        • MaterialDesign
          • BottomNavigationBar
          • CardView
          • Elevation高度、shadows阴影、clipping裁剪、tint着色
          • TouchFeedbackRipple波纹动画
      • Volley完全解析——使用、源码
      • Android围住神经猫的实现
      • LookLook剖析,架构概述——MVP、Retrofit+RxJava
      • Android性能优化之渲染
    • Browser
      • 浏览器的工作原理
    • HTML
      • DOCTYPE标签、XHTML与HTML的区别
    • CSS
      • CSS的继承性、层叠性、权重
      • CSS浮动float详解(一):标准文档流
      • CSS浮动float详解(二):使用float
      • CSS浮动float详解(三):清除浮动方案
    • Tools Lib
      • JavaScript 文件下载解决方案-download.js
      • js-url 用于url的js开源库
      • jsuri 用于操作url的js开源库
      • window offset
    • React
      • 模块化和组件
      • 组件的三大核心属性
      • 事件处理
      • 表单数据收集
      • 生命周期
      • DOM的diff算法
      • 工程化
        • 脚手架create-react-app
        • 工程结构和模块化
      • 路由
  • Design
    • 产品设计
      • 交互设计
由 GitBook 提供支持
在本页
  • 配置Shell
  • 编写并执行shell脚本
  • 变量
  • 环境变量
  • 自定义变量
  • 注释
  • 数据类型
  • string 字符串
  • 数组类型
  • 可执行的字符串
  • 运算符
  • 算数运算符
  • 关系运算符
  • 布尔运算符
  • 逻辑运算符(短路运算符)
  • 字符串运算符
  • 文件测试运算符
  • echo
  • test
  • read
  • declare
  • 流程控制
  • if
  • case
  • for
  • while
  • break 和 continue
  • 函数
  • Shell的参数传递

这有帮助吗?

在GitHub上编辑
  1. Programming Language
  2. Script Language

Shell

上一页BAT下一页Markup Language

最后更新于2年前

这有帮助吗?

Shell:壳

Shell是一个命令行解释器,它为用户提供了一个向Linux内核发送请求以便运行程序界面的系统级程序,用户可以用Shell来启动、挂起、停止甚至是编写程序。

计算机不认识ASCII字符,需要Shell接收ASCII并翻译给计算机。

目前,Shell共有两种类型:

  • Bourne Shell: 1979年Unix就开始使用Bourne Shell,主文件名为sh(功能比较简单,不常用)

  • C Shell:C Shell 主要在BSD版本的Unix系统中使用,其语法与C类似而得名(BSD:Unix版本)

Shell的两种主要语法类型就是 Bourne Shell 和 C Shell,这两种语法不兼容:

  • Bourne Shell 家族:

    • sh

    • ksh

    • bash(linux标准)

    • psh

    • zsh

  • C Shell 家族:

    • csh

    • tcsh (unix)

配置Shell

我们可以通过如下命令查看当前操作系统使用的shell类型:

echo $SHELL

也可以查看当前操作系统支持的shell版本:

vi /etc/shells

切换当前的shell:

sh #切换到sh,这是子shell,退出就是父shell
bash #切换到bash,这是子shell,退出就是父shell

编写并执行shell脚本

一个shell脚本需要在最前面指定脚本解释器:

#!/bin/bash

创建一个hello world脚本:

echo '#!/bin/bash
echo Hello World!
' > hello.sh

# 给脚本赋予执行权限
chmod ug+x hello.sh

# 直接运行脚本
./hello.sh

# 使用sh命令运行,等同于 bash ./hello.sh
sh ./hello.sh

# 使用source命令运行
# 该种方式不同于上面两种,不会打开新的进程去运行脚本文件,他的父进程直接为bash进程
# 而上面两种方式会打开一个 sh ./hello.sh 的子进程运行脚本文件
# 即,使用source执行脚本时,仍然处在bash这个进程中,而不是新进程,故可以使用bash中的任何变量
source ./hello.sh

子进程默认无法访问父进程中的变量,这是因为父进程中的变量默认对子进程不可见。 如果想要子进程可以访问父进程中变量,可以借助export命令将变量导出,被导出的变量对于进程的子进程是可见的这样就解决了无法访问父进程变量的问题。

变量

变量的分类:

  1. 用户自定义变量:脚本中的变量

  2. 环境变量:用于保存与操作系统操作环境相关的数据。变量可以自定义,但是对系统生效的环境变量名和变量作用是固定的。

  3. 位置参数变量:主要用于向脚本传递参数或者数据,变量名称不能自定义,变量作用是固定的

  4. 预定义变量:是Bash中已经定义好的变量,变量名不能自定义,变量作用也是固定的

变量命名规则:

  1. 变量名只能由字母数字和下划线组成,并且开头不可以是数字

  2. 变量名不得超过255个字符

  3. 变量名在有效范围内是唯一的

变量数据类型:

  1. 在Bash中,变量的默认类型是字符串类型

  2. Linux中,准确的说,只有string类型,所以不可以对数字进行直接运算

环境变量

用户自定义的环境变量:

export 变量名=变量值
或者
变量名=变量值
export 变量名

查看、修改、删除与普通变量一致。

对系统生效的环境变量喝变量作用是固定的。

查看系统中的所有环境变量:

# set 命令也会输出环境变量,但是也包含普通变量,比较乱
# env会输出当前系统中定义的所有环境变量
env

常用环境变量:

HOSTNAME:主机名
SHELL:当前SHELL
TERM:终端环境
HISTSIZE:历史命令最大条数(定义在/etc/profile文件中)
SSH_CLIENT:当前操作环境是用ssh连接的,这里记录客户端ip
SSH_TRY:ssh连接的终端时pts/1
USER:当前登陆用户

环境变量为什么大写:

因为系统命令全都是小写,这样可以将环境变量与系统命令区分。

自定义变量

定义:

变量名=变量值 #等号两侧不可以由空格
变量名="a b" #变量值之间有空格,需要双引号或者单引号包裹

调用:

echo $var_name

变量叠加:

x=1
y=${x}456    # 方式1
z="$x"456    # 方式2 

只读变量(注意不可unset):

url = 'http://baidu.com'
readonly url

查看所有变量:

set
set -u #默认输出一个不存在的变量,将会输出空字符串,执行此命令,将会提示变量不存在

删除变量:

unset 变量名

PATH变量

echo $PATH

/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/node-v10/bin:/root/bin:/usr/local/git/bin:/root/node-v8/bin:/root/bin
# 多个路径之间使用冒号:间隔

当终端输入一个执行文件的非绝对路径时,linux默认不支持直接执行这个命令,他将会先从命令别名中寻找命令,再从$PATH中定义的路径中依次寻找,找不到就抛出 command not found

往$PATH中添加路径:

# 使用变量叠加
PATH="$PATH:/root/sh"

什么是PS1和PS2

linux下的bash shell有两级用户提示符:

  1. 第一级是bash在等待命令输入时的提示符,可以通过在用户主目录下.bash_profile文件里设置PS1变量来实现。

  2. 当bash期待输入更多的信息以完成命令时将显示第二级提示符。

比如:你输入cp filename1 \,回车,此时就出现第二级提示符。\是续行的意思,默认的第二级提示符是>。 如果要改变第二级提示符,可以通过在.bash_profile文件里设置PS2变量来实现。

PS1变量

[root@Feathers ~]# echo $PS1
[\u@\h \W]\$

# $PS1 定义了当前系统的操作符
[ 对应[
\u 当前登陆用户
@  对应@
\h 当前主机名
\W 当前所在目录最后一个目录
]  对应]
\$ 当前用户提示符:超级用户#, 普通用户是$

命令提示符设置:

  • \d: 显示日期, 格式星期 月 日

  • : 显示24小时制时间,格式HH:MM:SS

  • \A: 显示24小时制时间,格式HH:MM

  • \H: 显示完整主机名

  • \$: 用户提示符。#root,$普通

  • \u: 用户名

  • \w: 显示所在目录完整名称

  • \W: 显示当前目录最后一个目录

PS2变量

定义换行提示符:

[root@Feathers ~]# echo $PS2
>

# 命令换行后
[root@Feathers ~]# ls \
>
# 其中 > 就是换行提示符

语系变量查询

locale:查询当前系统语系变量

[root@Feathers ~]# locale
LANG=en_US.UTF-8    #定义系统主语系变量,英文语系+UTF8编码,绝对了操作系统语言
LC_CTYPE="en_US.UTF-8"
LC_NUMERIC="en_US.UTF-8"
LC_TIME="en_US.UTF-8"
LC_COLLATE="en_US.UTF-8"
LC_MONETARY="en_US.UTF-8"
LC_MESSAGES="en_US.UTF-8"
LC_PAPER="en_US.UTF-8"
LC_NAME="en_US.UTF-8"
LC_ADDRESS="en_US.UTF-8"
LC_TELEPHONE="en_US.UTF-8"
LC_MEASUREMENT="en_US.UTF-8"
LC_IDENTIFICATION="en_US.UTF-8"
LC_ALL=     #定义整体语系变量

查看linux支持的所有语系:

locale -a | more 

查看系统默认语系(下次开机以后的系统生效的语言环境):

cat /etc/sysconfig/i18n

Linux中文支持:

  1. 前提:正确安装中文字体和中文语系

  2. 纯字符界面不支持中文显示,可以使用如zhcon插件来完成此功能(不推荐)

  3. 如果使用第三方工具连接,只需要保证第三方工具的语系设置正确即可

  4. 图形界面会自动支持

位置参数变量

位置参数:

命令 位置参数1 位置参数2 ...
位置参数变量
作用

$n

n代表数字,$0代表命令本身,$1-$9代表第一到第九个参数,10以上的参数需要使用${10}包含

$*

代表命令行中所有的参数,$*把所有的参数看成一个整体

$@

同样代表命令行中的所有参数,但是$@将每个参数区分对待

$#

代表命令行中所有参数的个数

具体示例:

#!/bin/bash
echo 共有参数"$#"
echo 参数是:"我是一个字符串,参数为,$*"
echo 参数是:"我是一个可循环的参数列表,$@"



num1=$1
num2=$2
sum=$(( $num1 + $num2))

echo 计算结果为:$sum

预定义变量

预定义变量
作用

$?

最后一条执行命令的返回状态,如果非0,代表正确执行

$$

当前进程的进程号 PID

$!

后台运行的最后一个进程的进程号

注释

# 以#作为单行注释
# 多行以#开头为多行注释

:<<EOF
我是注释内容
EOF

:<<ABC
我是注释内容,这是可以自定义结束符的注释
ABC

数据类型

准确地说,shell的数据类型只有string,没有数字等其他类型。

string 字符串

shell的字符串有两种表达方式:

  1. 使用单引号''表示的多行字符串,被包裹的文本不会进行变量转义

    str1='apple'
  2. 使用双引号""表示的多行字符串,被包裹的文本会做变量转义(有必要需要加入花括号区分界限)

    str2="${str1}很好吃"
  3. 如果字符串没有空格,可以去除单双引号表示

    str3=orange

字符串拼接:

str1="hello1"
str2="hello2"

str3=$str1$str2
echo $str3

str4='你好'$str1
echo $str4

str5="你好$str2"
echo $str5

获取字符串长度:

str1=myqq.com
echo ${#str1}

字符串截取:

str1='abcdefg'

# 从0截取,截取4位字符
# abc
echo ${str1:0:4}

# 从1截取,共截取3位字符
# bcd
echo ${str1:1:3}

数组类型

bash支持一维数组,并且不限定数组大小。数组的下标从0开始编号,且元素使用小括号定义。

定义并访问数组:

# 定义数组 idea -> array create
favs=("足球" "篮球" "乒乓球" "保龄球")

# 访问指定的下标 idea -> array at index
fav=${favs[1]}

# 设置指定下标的值 idea -> array set element
fav[1]="哈哈"

# 添加元素 idea -> array add 
favs+=("羽毛球")

# 获取数组的所有元素 idea  -> array all
echo ${favs[@]}

# 获取数组的长度 idea  -> array length
length=${#favs[@]}
# 或者
length=${#favs[*]}

# 循环数组 idea -> array iteration
for item in ${favs[@]}; do
    echo "$item"
done

# 删除数组的某个元素 idea -> array delete at
unset favs[0]

# 删除真个数组 -> idea -> array delete
unse favs

可执行的字符串

echo `echo hello`

运算符

算数运算符

使用算数运算符共有以下几种方式:

  • $((运算符))或$[运算符] (推荐)

  • expr

  • let

  • declare (不推荐)

$((运算符))或$[运算符]

aa=11
bb=22
cc=$(($aa+$bb))
dd=$[$aa+$bb]
echo $cc
# 推荐$((运算符))

shell支持的数值运算:

与或运算使用0和1表示

expr

a=10
b=20

echo `expr $a + $b`
echo `expr $a - $b`
echo `expr $a \* $b`
echo `expr $b / $a`
echo `expr $b % $a`

反引号里面的内容将会被作为命令、脚本直接运行得到结果

let

let命令是Bash中用于计算的工具,提供常用运算符还提供了方幂**运算符。在变量的房屋计算中不需要加上$来表示变量,如果表达式的值是非0,那么返回的状态值是0;否则,返回的状态值是1。

let a=5+4 b=9-3
echo $a $b

let "t1 = ((a = 5 + 3, b = 7 - 1, c = 15 - 4))"
echo "t1 = $t1, a = $a, b = $b"

declare -i

使用declare -i,不推荐:

aa=111
bb=222
declare -i cc=${a}+${b}
echo ${cc}
333

关系运算符

关系运算符用于判断两个数字字符串之间的关系,如果字符串不是数字字符串,将无法处理。

a=10
b=20

if [$a -eq $b]
then
   echo "$a -eq $b : a 等于 b"
else
   echo "$a -eq $b : a 不等于b"
fi

# -eq 等于         idea-> number equal
# -ne 不等于       idea-> number not equal
# -gt 大于         idea-> number greater
# -lt 小于         idea-> number less
# -ge 大于等于      idea-> number greater or equal
# -le 小于等于      idea-> number less or equal

布尔运算符

布尔运算符共有三种与或非:

a=10
b=20

# 非
if [$a != $b]
then
   echo "$a != $b: a不等于b"
else 
   echo "$a == $b: a等于b"
fi

# 与
if [$a -lt 100 -a $b -gt 15 ]
then
   echo "$a 小于 100 且 $b 大于 15:返回true"
else
   echo "$a 小于 100 且 $b 大于 15:返回false"
fi

# 或
if [$a -lt 100 -o $b -gt 15 ]
then
   echo "$a 小于 100 或 $b 大于 15:返回true"
else
   echo "$a 小于 100 或 $b 大于 15:返回false"
fi

逻辑运算符(短路运算符)

逻辑运算符需要用双方括号包裹

a=10
b=20

if [[ $a -lt 100 && $b -gt 100]]
then
   echo "返回true"
else 
   echo "返回false"
fi

if [[ $a -lt 100 || $b -gt 100]]
then
   echo "返回true"
else
   echo "返回false"
fi

字符串运算符

a=zhangsan
b=lisi

# 相等判断(在idea中,快捷输入为 string equal)
if [$a == $b]
then
   echo 'a 和 b是两个完全相同的字符串'
else
   echo 'a 和 b是两个不同的字符串'
fi

# 不等判断(在idea中,快捷输入为 string not equal)
if [$a != $b]
then
   echo 'a 和 b是两个不同的字符串'
else
   echo 'a 和 b是两个完全相同的字符串'
fi

# 空判断(在idea中,快捷输入为 string is empty)
if [ -z $a ]
then 
   echo "a 变量是一个空字符串"
else
   echo "a 变量不是一个空字符串"
fi

# 非空判断(在idea中,快捷输入为 string not empty)
if [-n $a]
then 
   echo 'a 不是一个空字符串'
else 
   echo 'a 是一个空字符串'
fi 

# 或者
if [$a]
then
   echo 'a 不是一个空字符串'
else
   echo 'a 是一个空字符串'
fi

文件测试运算符

file="/var/node/test.sh"

# 文件是否可读(在idea中,快捷输入为 file readable)
if [ -r $file ]
then
   echo "文件可读"
else 
   echo "文件不可读"
fi

# 文件是否可写(在idea中,快捷输入为 file writable)
if [ -w $file ]
then
   echo "文件可写"
else
   echo "文件不可写"
fi

# 文件是否可执行(在idea中,快捷输入为 file executable)
if [ -x $file ]
then
   echo "文件可以执行"
else
   echo "文件不可执行"
fi

# 判断文件是否存在(在idea中,快捷输入为 file exists)
if [ -f $file ]
then
   echo "目标是一个文件,且存在"
else
   echo "文件不存在"
fi   

# 判断目录是否存在 (在idea中,快捷输入为 directory exists )
if [ -d $file]
then
   echo "目标是一个目录,且存在"
else
   echo "目录不存在"
fi

# 判断路径是否存在,既可以判断文件,又可以判断目录(在idea中,快捷输入为 path exists)
if [-e $file]
then
   echo "目标路径存在"
else
   echo "目标路径不存在"
fi

echo

读作 ai kou

echo "Hello World"
# 显示转义字符
echo "\"Hello World\""
# 显示变量
name=zhangsan
echo "$name HelloWorld"
# echo默认会显示换行
echo "你好"
echo "世界"
# 除了\",echo的双引号字符不支持任何转义字符,如果需要支持转义字符,需要增加-e选项
echo -e "Hello \n World"
# 使用 \c 去除行为换行
echo -e "Hello\c"
echo "World"
# 使用单引号进行原样输出
echo '"hello"World $name' #"hello"World $name
# 重定向到文件(覆盖)
echo "hello" > a.txt
# 重定向到文件(追加)
echo "hello" >> a.txt
### 颜色
# 30m 黑色,31m 红色,32m 绿色,33m 黄色
# 34m 蓝色,35m 洋红,36m 青色,37m 白色
# \e[1;31m 开启颜色,颜色为红色
# \e[0m 关闭颜色
echo -e "\e[1;31m 我长得很帅 \e[0m" # 注意空格

test

test命令可以用于替换if语句中的中括号:

num1=100
num2=200
if test $[num1] -eq $[num2]
then
   echo "两数相等"
else
   echo "两数不等"
fi

read

read [选项] [变量名]
-p "提示信息:"在等待read输入时,输出提示信息
-t 秒数:read命令会一直等待用户输入,使用此选项可以指定等待时间
-n 字符数:read命令会只接受指定的字符数
-s 隐藏输入数据,适用于机密信息的输入

示例:

#!/bin/bash
read -p "请输入你的姓名:   " -t 30 name
read -p "请输入密码:      " -s -n 6 password
echo -e "\n$name : $password"

declare

再Linux中变量全是字符串类型,所以变量无法直接进行运算,所以我们需要借助declare命令声明变量类型:

declare [+/-][选项] 变量名
- : 给变量设定类型属性
+ : 取消变量类型属性

-a: 声明为数组类型
-i: 声明为整型  integer
-x: 声明为环境变量  
-r: 声明为只读变量  readonly
-p: 显示指定变量的被声明的类型

整型:

#声明一个整型
declare -i test=123
#声明的整型可以进行数值运算
declare a=100
declare b=200
declare -i c=${a}+${b}

$ echo ${c}
300

数组:

声明变量:
declare -a onepiece[0]=LuFei
onepiece[1]=NaMei
onepiece[2]=SuoLong

查看数组中的所有元素:
echo ${onepiece[*]}
查看数组中的第一个元素:
echo ${onepiece}
echo ${onepiece[0]}
查看数组中的第n个元素:
echo ${onepiece[n]}

声明环境变量:

declare -x test=123
#其实export只是对declare -x命令的包装,最终调用的都是declare -x命令

列出系统中所有变量的类型:

declare -p
#其中 -- 代表没有声明变量类型,或者变量类型被+取消了

只读变量:

#不要使用,临时变量,但是无法删除,无法修改值,无法修改类型
declare -r test=111

流程控制

if

a=10
b=20
if [ $a == $b ]
then
   echo "a 等于 b"
elif [ $a -gt $b ]
then
   echo "a 大于 b"
elif [ $a -lt $b ]
then
   echo "a 小于 b"
else
   echo "没有符合的条件"
fi

条件可以为 [[]]代表可以使用短路逻辑运算符,(())代表可以使用>、<直接判断数字,比如if (( $a > $b ))

case

通常用来处理枚举:

echo '输入 1 到 4 之间的数字:'
echo '你输入的数字为:'
read aNum
case $aNum in
    1)  echo '你选择了 1'
    ;;
    2)  echo '你选择了 2'
    ;;
    3)  echo '你选择了 3'
    ;;
    4)  echo '你选择了 4'
    ;;
    *)  echo '你没有输入 1 到 4 之间的数字'
    ;;
esac

不仅是数字,文本也可以:"hobby") echo "你选择了 'hobby'"

for

# 循环有限的数字
for loop in 1 2 3 4 5
do
    echo "The value is: $loop"
done

# 循环有限的文本
for str in This is a string
do
    echo $str
done
# This
# is
# a
# string

# 循环数字范围
for i in {1..1000} ; do
    echo "$i"
done

# 循环数组
arr=(1 2 3 4)
for i in ${arr[@]}; do
    echo "$i"
done

while

int=1
while(( $int<=5 ))
do
    echo $int
    let "int++"
done

echo '按下 <CTRL-D> 退出'
echo -n '输入你最喜欢的网站名: '
while read FILM
do
    echo "是的!$FILM 是一个好网站"
done

无限循环:

while :
do
    command
done

while true
do
    command
done

for (( ; ; ))

break 和 continue

while :
do
    echo -n "输入 1 到 5 之间的数字:"
    read aNum
    case $aNum in
        1|2|3|4|5) echo "你输入的数字为 $aNum!"
        ;;
        *) echo "你输入的数字不是 1 到 5 之间的! 游戏结束"
            break
        ;;
    esac
done

while :
do
    echo -n "输入 1 到 5 之间的数字: "
    read aNum
    case $aNum in
        1|2|3|4|5) echo "你输入的数字为 $aNum!"
        ;;
        *) echo "你输入的数字不是 1 到 5 之间的!"
            continue
            echo "游戏结束"
        ;;
    esac
done

函数

函数的调用和参数:

funWithParam(){
    echo "第一个参数为 $1 !"
    echo "第二个参数为 $2 !"
    echo "第十个参数为 $10 !"
    echo "第十个参数为 ${10} !"
    echo "第十一个参数为 ${11} !"
    echo "参数总数有 $# 个!"
    echo "作为一个字符串输出所有参数 $* !"
}
funWithParam 1 2 3 4 5 6 7 8 9 34 73

通过$?获取函数返回值:

funWithReturn(){
    echo "这个函数会对输入的两个数字进行相加运算..."
    echo "输入第一个数字: "
    read aNum
    echo "输入第二个数字: "
    read anotherNum
    echo "两个数字分别为 $aNum 和 $anotherNum !"
    return $(($aNum+$anotherNum))
}
funWithReturn
echo "输入的两个数字之和为 $? !"

Shell的参数传递

执行Shell脚本时,可以向脚本传递参数,脚本内可以通过$n,n代表一个数字,来获取传入的参数信息。相关的参数处息如下:

参数处理
说明

$#

参数个数

$*

所有的参数,以一个字符串显示

$$

脚本运行的当前的id号

$!

后台运行的最后一个进程的ID号

$?

显示上一个命令的运行状态,如果为0代表成功,其他表示失败

$0

当前执行的脚本的文件名称

echo "执行的文件名为 $0"
echo "第一个参数为 $1"
echo "第二个参数为 $2"
1541301397256
1540905917702
1541149257950
1542418674368