Skip to content

Shell脚本

编程语言分类

编译型语言

  • 需将源代码编译成可执行文件才能运行
  • 示例:C、C++、C#、Java
  • 特点:全部代码无语法错误才能编译运行

解释型语言

  • 无需编译,直接逐行解释执行
  • 示例:JavaScript、TypeScript、Python、Shell
  • 特点:逐行执行,即使后续语句有错,前面正确语句仍可运行

Shell解析器

  • /bin/bash
  • /bin/sh

编写脚本时需在文件首行指定解析器:#!/bin/bash

Shell脚本文件

  • 扩展名:.sh
  • 简单示例:
    shell
    #!/bin/bash
    # 这是注释行
    echo "hello shell"  # 输出文本到终端

运行Shell脚本

  • 方法:./脚本名.sh

注意

  1. 脚本需有可执行权限:chmod +x 脚本名.sh
  2. 编辑时需使用Unix(LF)换行模式(推荐用vim编辑)

Shell变量

变量定义与使用

  • 定义变量名=值(等号两侧不能有空格)
    shell
    NUM=123  # 定义变量
  • 引用
    shell
    echo $NUM     # 输出变量值
    echo ${NUM}   # 推荐写法

变量类型

自定义变量

  • 用户自定义的变量
    shell
    LS=`ls`  # 反引号执行命令并赋值

位置变量

变量含义
$0脚本名称(如 ./demo.sh)
$1第一个参数
$2第二个参数
......(最多支持9个参数)
$#参数个数(不含$0)
$@所有参数列表(独立字符串)
$*所有参数合并为单个字符串
$?上条命令退出码(0-255)

环境变量

  • 系统预定义变量
    shell
    echo $PATH  # 可执行文件搜索路径
    echo $HOME  # 当前用户家目录
    export     # 查看所有环境变量

数组

  • 定义数组名=(值1 值2 值3)
    shell
    Array=(1 2 3 4)
  • 操作
    shell
    echo ${Array[0]}   # 访问下标0
    Array[1]=100       # 修改下标1的值
    echo ${Array[*]}   # 输出所有元素

注意

  1. 元素用空格分隔,下标可不连续(空缺位置为空)
  2. 下标从0开始

Shell语句

输入语句

  • read:从终端读取数据
    shell
    read NUM1 NUM2  # 读取两个数据
    常用参数
    参数功能
    -p显示提示符(read -p "提示" var
    -s静默输入(不显示内容)
    -t超时时间(秒)
    -a读取到数组(read -a arr

输入重定向

  • 从文件读取而非键盘
    shell
    read name < input.txt  # 从文件读取一行

输出语句

  • echo:输出内容到终端
    shell
    echo "Hello World"

输出重定向

符号功能
>覆盖写入文件
>>追加写入文件
2>错误输出重定向
shell
echo "内容" > output.log   # 覆盖写入
echo "追加" >> output.log  # 追加写入

算术运算

  • expr:整数运算命令
    shell
    expr 1 + 2          # 输出3
    SUM=`expr 1 \* 2`   # 乘法需转义*

注意:运算符两侧必须有空格

测试语句(test)

字符串测试

测试条件含义示例
"str1" = "str2"字符串相等test "abc" = "abc"
"str1" != "str2"字符串不等test "a" != "b"
-z "str"字符串为空(长度0)test -z ""
-n "str"字符串非空test -n "abc"

整数测试

测试条件含义示例
num1 -eq num2相等test 123 -eq 123
num1 -ne num2不等test 123 -ne 456
num1 -gt num2大于test 100 -gt 50
num1 -lt num2小于test 50 -lt 100
num1 -ge num2大于等于test 100 -ge 100
num1 -le num2小于等于test 50 -le 100

文件测试

测试条件含义示例
-d 文件是否为目录test -d /home
-f 文件是否为普通文件test -f test.txt
-L 文件是否为链接文件test -L symlink
-r 文件是否可读test -r file
-w 文件是否可写test -w file
-x 文件是否可执行test -x script.sh
-s 文件文件是否非空test -s data.log
file1 -nt file2file1是否比file2新test a.txt -nt b.txt
file1 -ot file2file1是否比file2旧test a.txt -ot b.txt

简写:可用[ ]替代test(两侧需留空格)

shell
[ -f "test.txt" ]  # 等价于 test -f test.txt

结构性语句

分支语句

if分支

shell
if [ 条件 ]
then
    # 条件成立执行
elif [ 条件2 ]
then
    # 条件2成立执行
else
    # 其他情况执行
fi

示例

shell
if [ -f "$filename" ]
then
    echo "$filename 是普通文件"
else
    echo "$filename 不是普通文件"
fi

case分支

shell
case $变量 in
    模式1)
        语句块1
        ;;  # 必须双分号结尾
    模式2)
        语句块2
        ;;
    *)      # 默认匹配
        默认语句块
        ;;
esac

通配符

  • *:匹配任意字符
  • ?:匹配单个字符
shell
case $file in
    *.txt)
        echo "文本文件"
        ;;
    *.sh)
        echo "脚本文件"
        ;;
    *)
        echo "未知文件"
        ;;
esac

循环语句

for循环

shell
# 列表形式
for var in 值1 值2 值3
do
    echo $var
done

# C语言形式
for ((i=0; i<10; i++))
do
    echo $i
done

while循环

shell
while [ 条件 ]
do
    # 循环体
done

示例

shell
num=0
while [ $num -le 10 ]
do
    echo $num
    num=`expr $num + 1`  # 数值递增
done

控制语句

  • break:跳出循环
  • continue:跳过本次循环

Shell函数

shell
函数名() {
    函数体
    return 返回值  # 可选
}

特点

  1. 无参数列表(使用位置变量$1, $2...传参)
  2. 无返回值类型(通过return返回整数,或直接输出结果)
  3. 无作用域限制(可访问脚本全局变量)

示例

shell
sum() {
    s=`expr $1 + $2`
    echo $s   # 输出结果
    # 或 return $s (返回值范围0-255)
}

# 调用
result=$(sum 10 20)
echo "结果为:$result"

作业

  1. 编写脚本生成C++文件模板:
shell
   #!/bin/bash
   if [ $# -eq 0 ]; then
       echo "请提供文件名"
       exit 1
   fi
   cat > $1.cpp << EOF
   #include <iostream>
   using namespace std;
   
   int main() {
       // 代码
       return 0;
   }
   EOF
   echo "已创建 $1.cpp"
   

2. 实现简单计算器:  
   ```shell
   #!/bin/bash
   if [ $# -ne 3 ]; then
       echo "用法: 计算器 操作数1 运算符 操作数2"
       exit 1
   fi
   
   case $2 in
       +) echo $(($1 + $3)) ;;
       -) echo $(($1 - $3)) ;;
       *) echo $(($1 * $3)) ;;  # 仅支持加减乘
       /) echo "除法需特殊处理" ;;
   esac

知识如风,常伴吾身