shell 语法快速入门

前言

Shell 既是一种命令语言,又是一种程序设计语言。指一种应用程序,用户通过这个程序访问操作系统内核的服务

通常所说的 Shell 通常都是指 Shell 脚本,即为 Shell 编写的脚本程序

总结:Shell 只要记住一些特殊的语法格式,其它的同正常编程相同

shell 模板

#!/bin/bash
echo "Hello World !"

#! 指定 Shell 解释器,即使用哪种 Shell。Shell 种类众多,如 Bourne Shell、Bourne Again Shell、C Shell 等,常用 Bash

注:

  • 默认后缀为 .sh
  • 执行需要具有执行权限
  • 直接实现解释器运行 sh hello.sh

变量

变量用于存储数据值的名称

定义规则

VAR_NAME="number"
readonly VAR_NAME_ONLY  # 只读变量
  • 变量与等号之间不允许空格
  • 变量由字母、数字和下划线组成
  • 不能以数字开头
  • 默认使用大写字母
  • 避免使用空格
  • 只读变量不能改变值,无法删除

使用规则

$VAR_NAME  # 使用变量
 
unset VAR_NAME  # 删除变量

变量类型

字符串变量:使用双引号("")定义字符串

  • 单引号中的变量无效

整型变量:declare 或 typeset 声明

数组变量:

# 索引数组
ARR={1 2 3}
# 关联数组
declare -A ARRAY
ARRAY["key"]="val"

环境变量

环境变量:由操作系统或用户设置的特殊变量,用于配置 Shell 的行为和影响其执行环境
使用 set 命令显示系统变量

HOME PWD SHELL USER PATH

特殊参数

变量 含义
$n 访问命令行中第 n 个参数,$0 为命令本身,n 大于 10 需要使用大括号包含
$* 指代命令行中全部参数,视为整体
$@ 指定命令行中全部参数,分别对待
$# 统计命令行参数个数
$$ 获取当前进程的 PID
$! 后台运行的最后一个进程的 PID
&? 上一个命令的退出状态(0 为成功)
$- 显示 Shell 使用的当前选项,同 set

字符串处理

单引号

  • 单引号里的任何字符都会原样输出
  • 单引号字符串中的变量是无效的
  • 单引号字符串中不能出现单独一个的单引号

双引号

  • 双引号里可以有变量
  • 双引号里可以出现转义字符

获取字符串长度

string="abcd"
echo ${#string}   # 输出 4

变量为字符串时,${#string} 等价于 ${#string[0]}

提取子字符串

string="runoob is a great site"
echo ${string:1:4} # 输出 unoo

注:第一个字符的索引值为 0。

查找子字符串

string="runoob is a great site"
echo `expr index "$string" o`  # 输出 4

注: 以上脚本中 ` 是反引号,而不是单引号 '

数组

bash 支持一维数组(不支持多维数组),并且没有限定数组的大小。

,数组元素的下标由 0 开始编号。获取数组中的元素要利用下标,下标可以是整数或算术表达式,其值应大于或等于 0。

数组名=(值1 值2 ... 值n) # 定义数组

${数组名[下标]} # 访问元素

echo ${array_name[@]}  # 指代全部元素

注释

单行注释

以 # 开头的行就是注释,会被解释器忽略
例:

#--------------------------------------------
# 这是一个注释
#--------------------------------------------

多行注释

:<<EOF
注释内容...
注释内容...
注释内容...
EOF

EOF 也可以使用其他符号代替 如 !

使用冒号 : 命令,并用单引号 ' 将多行内容包括同样可行

: '
这是注释的部分。
'

运算

$((oper))

$[oper]

expr oper # 值同运算符之间存在空格

算术运算符

运算符 说明
+ 加法
- 减法
\* 乘法
/ 除法
% 取余
= 赋值
== 相等。用于比较两个数字,相同则返回 true
!= 不相等。用于比较两个数字,不相同则返回 true

关系运算符

运算符 说明
-eq 检测两个数是否相等,相等返回 true
-ne 检测两个数是否不相等,不相等返回 true
-gt 检测左边的数是否大于右边的,如果是,则返回 true
-lt 检测左边的数是否小于右边的,如果是,则返回 true
-ge 检测左边的数是否大于等于右边的,如果是,则返回 true
-le 检测左边的数是否小于等于右边的,如果是,则返回 true

布尔运算符

运算符 说明
! 非运算,表达式为 true 则返回 false,否则返回 true
-o 或运算,有一个表达式为 true 则返回 true
-a 与运算,两个表达式都为 true 才返回 true

逻辑运算符

运算符 说明
&&
11

字符串运算符

运算符 说明
= 检测两个字符串是否相等,相等返回 true
!= 检测两个字符串是否不相等,不相等返回 true
-z 检测字符串长度是否为0,为0返回 true
-n 检测字符串长度是否不为 0,不为 0 返回 true
$ 检测字符串是否不为空,不为空返回 true

文件运算符

操作符 说明
-b file 检测文件是否是块设备文件,如果是,则返回 true
-c file 检测文件是否是字符设备文件,如果是,则返回 true
-d file 检测文件是否是目录,如果是,则返回 true
-f file 检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回 true
-g file 检测文件是否设置了 SGID 位,如果是,则返回 true
-k file 检测文件是否设置了粘着位(Sticky Bit),如果是,则返回 true
-p file 检测文件是否是有名管道,如果是,则返回 true
-u file 检测文件是否设置了 SUID 位,如果是,则返回 true
-r file 检测文件是否可读,如果是,则返回 true
-w file 检测文件是否可写,如果是,则返回 true
-x file 检测文件是否可执行,如果是,则返回 true
-s file 检测文件是否为空(文件大小是否大于0),不为空返回 true
-e file 检测文件(包括目录)是否存在,如果是,则返回 true
-S 文件是否 socket
-L 文件是否存在且为符合链接

自增自减

let 命令允许对整数进行算术运算

let num++
let num--

命令

echo

用于在标准输出显示文本或变量值

echo [选项] [字符串]
  • -n : 不换行输出
  • -e : 启动转义字符解释
转义序列 说明
\n 换行
\t 水平制表符
\v 垂直制表符
\b 退格
\r 回车
\\ 反斜杠字符本身

1. 创建简单菜单

echo -e "\n\033[1mSystem Menu\033[0m"
echo "1. Check disk space"
echo "2. List running processes"
echo "3. Show system info"
echo -n "Please enter your choice [1-3]: "

2. 进度条模拟

echo -n "Progress: ["
for i in {1..20}; do
    echo -n "#"
    sleep 0.1
done
echo "] Done!"

3. 生成配置文件

cat <<EOF | sudo tee /etc/myapp.conf
# Generated by script on $(date)
[Database]
host = localhost
port = 3306
user = appuser
password = secret123
EOF

printf

printf 是一个用于格式化输出的 Shell 命令,它源自 C 语言的 printf() 函数
与echo不同,printf 不会自动添加换行符,并且可以精确控制输出的格式

print format-string [argument...]
  • format-string:(普通字符+格式说明符)字符串
  • 变量

格式说明符

字符 含义
%s 字符串
%d 整数
%f 浮点数
%c 字符
%x 十六进制
%o 八进制
%b 二进制
%e 科学计数法
序列 说明
\a 警告字符,通常为ASCII的BEL字符
\b 后退
\c 抑制(不显示)输出结果中任何结尾的换行字符(只在%b格式指示符控制下的参数字符串中有效),而且,任何留在参数里的字符、任何接下来的参数以及任何留在格式字符串中的字符,都被忽略
\f 换页(formfeed)
\n 换行
\r 回车(Carriage return)
\t 水平制表符
\v 垂直制表符
\\ 一个字面上的反斜杠字符
\ddd 表示1到3位数八进制值的字符。仅在格式字符串中有效
\0ddd 表示1到3位的八进制值字符

流程控制

if

if [ ]
then
    ...
elif [ ]
then 
    ...
else
    ...
fi

case

case var in
模式1)
    ...
;;
模式2)
    ...
;;
esac

for

for var in item1 item2 ...
do 
    ...
done

while

while [ ]
do 
    ...
done

until

until []
do 
    ...
done

函数

function funname() 
{
  
}