Linux Shell 脚本:从零到进阶的实战笔记

Linux Shell 脚本:从零到进阶的实战笔记


1. Shell 脚本是什么?怎么跑?

  • Shell 脚本:纯文本程序,用 Shell 语法完成任务;相比用 C/C++ 去写小工具,"脚本化"的门槛低、迭代快,适合运维与批处理。

  • 两种执行方式

    1. bash script.sh(显式用哪个解释器)
    2. chmod +x script.sh && ./script.sh(依赖首行 Shebang

    Shebang 常写 #!/bin/bash#!/bin/sh;如果用"方式 1"执行,首行 Shebang 不生效(因为你已经指定了解释器)。

  • "Hello world" 极简示例:

    bash 复制代码
    #!/bin/bash
    echo "hello world"

    (文档也在示例中强调 echo 输出后自带换行。)


2. 变量与"弱类型":赋值、拼接、位置参数

  • 赋值与替换

    • 赋值:name=value等号两边不能有空白
    • 使用:$name 才是"变量的值",这叫变量替换
  • 类型

    • Shell 变量无需声明类型,默认按字符串理解,"用法决定类型"。
  • 位置参数

    • $0 脚本名;$1...$9 参数 1~9;${10} 表示第 10 个;$@/$* 表示"全部参数"(展开规则略有差异)。→(目录大纲中有"位置参数/退出状态"专节)

3. 常见运算与判断:算术/字符串/文件测试/逻辑

  • 算术(整数)

    • (( ))$(( )) 做加减乘除与自增自减;支持 let(文档示例里也出现了 let)。
  • 比较与逻辑

    • 字符串判空:-z, -n(配 [ ] 时需加引号[ -z "$name" ])。
    • 逻辑与/或:[[ ... && ... ]][[ ... || ... ]](在 [[ ]] 下写更安全)。
  • 文件测试(存在/类型/权限/特殊位)

    • 常见:-e/-f/-d/-r/-w/-x;特殊位:SGID/SUID 的语义与场景也有解释(目录 SGID 让新文件自动继承组;SUID 以文件所有者权限执行)。

    • 示例:当前脚本是否可执行

      bash 复制代码
      if [ -x "$0" ]; then echo "有执行权限"; else echo "没有执行权限"; fi

      (文档给了完整示例)


4. 分支控制:if / case / select

  • if/elif/else :典型登录校验;注意在 [[ ]] 中连写 &&

  • case :适合"多分支输入分发";支持模式 * ? [ ] |

    bash 复制代码
    case "$addr" in
      "changsha") echo "去长沙旅游"; echo "去长沙吃臭豆腐";;
      "beijing")  echo "去北京旅游"; echo "去北京故宫看三宫六院";;
      *)          echo "回家休息";;
    esac

    (语法与示例都在文档中)

  • select:交互式菜单(文档"目录"中列出),在需要"让用户选项"的场景很有用。


5. 循环:for(三种姿势)/ while / until

5.1 for 三连

  • 列表式

    bash 复制代码
    for item in $(ls); do
      echo "找到文件:$item"
    done

    (演示"命令输出作为列表")

  • 配合 seq

    bash 复制代码
    s=0
    for i in $(seq 1 10); do ((s+=i)); done
    echo "$s"

    seq 还能 -w 补零、-s 指定分隔符、-f 使用 printf 风格格式)
    批量创建带序号文件

    bash 复制代码
    for item in $(seq -f "file_%03g" 1 10); do
      touch "$item"
    done

    %03g → 左侧补零三位)

  • C 风格

    bash 复制代码
    s=0
    for ((i=1; i<=100; i++)); do ((s+=i)); done
    echo "$s"

    (整数循环写法更直观)

5.2 while

  • 基础写法(文档给了 let(( )) 两个版本):

    bash 复制代码
    s=0; i=1
    while (( i <= 100 )); do
      (( s += i )); (( i++ ))
    done
    echo "$s"

    break/continue 在 while/for 都可用)

5.3 until

  • 模板:until <条件>; do ...; done

  • 语义与 while 相反当条件为真时退出,否则继续循环。

    bash 复制代码
    i=1
    until (( i >= 10 )); do
      echo "第$i 次循环"
      ((i++))
    done

    (文档特别标注了"条件为真时退出"这一点,容易误解)


6. 函数:两种定义、参数、返回值(return vs echo)

  • 定义两种写法function f {}f() {} 都可。示例里让用户输入数字并回显平方:echo $((num*num))

  • 参数$# 参数个数;$1/$2 访问各参数。示例演示"传入 Rock Tony,打印参数个数与每个值"。

  • 返回值

    • return 仅 0--255(超过会溢出):

      bash 复制代码
      myFunc1(){ ((ret=$1+$2)); return $ret; }
      myFunc1 255 2; echo $?

      (第二次会溢出)

    • echo 可返回任意文本:

      bash 复制代码
      myFunc2(){ ((ret=$1+$2)); echo "$ret"; }
      ret=$(myFunc2 255 2); echo "$ret"

      (用命令替换接收)

    • **多次 echo 的"只取最后一行"**技巧:

      bash 复制代码
      myFunc(){ echo "China"; echo "ChangSha"; }
      ret=$(myFunc | tail -1)   # ret=ChangSha

      (文档明确给了"tail -1 取最后一行"的范式)


7. 递归:阶乘 & 目录 DFS

  • 阶乘(基线 + 递归步)

    bash 复制代码
    fact() {
      if (( $1 <= 1 )); then echo 1
      else
        local tmp=$(( $1 - 1 ))
        local result=$(fact "$tmp")
        echo $(( $1 * result ))
      fi
    }
    read -p "请输入一个正整数:" num
    result=$(fact "$num")
    echo "$num 的阶乘为: $result"

    (用 local 隔离变量、用命令替换把子结果带回)

  • 递归遍历目录(DFS)

    bash 复制代码
    list() {
      for fd in $1/*; do
        if [ -d $fd ]; then
          echo "$fd 是目录"
          list "$fd"
        else
          echo "$fd 是文件"
        fi
      done
    }
    list "/etc"

    (思路清晰:遇目录先打印再"下钻";生产中可加引号、防空匹配、处理符号链接)


8. 数组:一维、从 0 开始、遍历与长度

  • 语法arr=(v1 v2 ... vn)成员用空格分隔,不用逗号;索引从 0 开始。

  • 示例

    bash 复制代码
    data=(1 3 5 "长沙")
    echo "${data[0]}"            # 第 1 个
    echo "元素个数: ${#data[@]}" # 长度
    for item in "${data[@]}"; do echo "$item"; done

    (遍历必须用 "${arr[@]}",这点文档也点名强调)

  • 文档说明 :Bash 原生只支持一维数组(关联数组属另一个概念,文档未展开)。


9. 文件 I/O:逐行写入与读取

  • 写文件(交互式追加)

    bash 复制代码
    rm -rf users.txt
    while true; do
      read -p "请输入姓名: " name
      read -p "请输入电话: " tel
      echo $name $tel >> users.txt
      read -p "输入 exit 退出: " answer
      if [[ $answer == "exit" ]]; then break; fi
    done
    Exit 0   # ← 文档此处大小写写成 Exit,会报 "command not found"

    (逻辑 OK,但 Exit 应为 exit,且删文件不必 -r。示例原文如此,记录以便你对照)

  • 读文件(逐行解析成"数组")

    bash 复制代码
    fileName="users.txt"
    cat $fileName | while read item; do
      echo "读到数据:$item"
      array=($item)
      echo "一共有${#array[@]}个数据: "
      echo "第 1 个:${array[0]} 第 2 个: ${array[1]}"
    Done
    Exit 0

    说明:这段用于演示"按空白切分"后取前两个字段,但示例里把 done/exit 写成 Done/Exit(大小写错误);实际应为小写。


10. 常见易错点(结合文档示例逐条"排坑")

  1. 大小写敏感done/exit 必须小写;示例中 Done/Exit 会报错。
  2. until 的语义:条件为真就退出;若一开始条件已真,循环体一次都不会进。
  3. 数组遍历 :应使用 "${arr[@]}",否则含空格的元素会被拆裂。
  4. 文件测试加引号[ -z "$name" ],防止空值导致语法歧义。
  5. 逻辑与/或 :在 [[ ]] 中连写 &&/|| 更稳;文档示例就是如此。
  6. return vs echoreturn 只能 0--255;要返回任意值,用 echo + 命令替换,并可 | tail -1 取最后一行。
  7. for + seq 的格式化 :记住 %03g 之类的 -f 用法(补零、定宽)很实用。

11. 实战练习清单(边学边做)

  • 练习 A:批量建 100 个目录并写入占位文件

    bash 复制代码
    for d in $(seq -f "day_%03g" 1 100); do
      mkdir -p "$d" && echo "hi" > "$d/readme.txt"
    done
    ```(把 `seq -f` 用熟):contentReference[oaicite:47]{index=47}
  • 练习 B:用 case 做"环境切换"脚本(dev/test/prod),复用上面的 case 模式匹配范式。

  • 练习 C:把"阶乘递归"改成 迭代版本(比较性能与可读性)。

  • 练习 D:把"读 users.txt"改成制表符分隔**,并对字段数做校验("不满两列就报错跳过"),巩固数组使用。


12. 速查表(贴墙上)

  • 运行方式:bash script.sh / chmod +x && ./script.sh;Shebang 指定解释器。
  • 变量:a=1echo "$a";拼接:a="${a} China"
  • 判断:[[ $x == $y && -n "$z" ]];文件测试:-e/-f/-d/-r/-w/-x
  • 循环:for/while/untilbreak/continue 都支持;until 条件真时退出。
  • 函数:f(){ ... };参数 $#/$1...return 0--255;val=$(f) 接收 echo 值。
  • 数组:arr=(a b "长沙")${#arr[@]} 长度;"${arr[@]}" 遍历。
  • 文件 I/O:写 >>;读 while read;示例中 Done/Exit 大小写需改成小写才可运行。

结语

这份笔记基本把 PDF 里的知识点"结构化 + 实战化"整理了出来:入门要素(变量/判断/循环)函数与返回值的取舍递归与 DFS 思路数组与 I/O 的常见坑。配合上面的练习,你可以很快搭起稳妥的脚本骨架。

相关推荐
宁雨桥2 小时前
保姆级教程:windows和linux双系统的电脑如何无副作用,安全删除linux
linux·windows·电脑
孙克旭_2 小时前
kind部署K8S集群并将“修仙业务“部署到kind集群
linux·运维·云原生·kubernetes·kind
ooolmf2 小时前
3.1.1话题,发布小说笔记20250923
笔记
IT成长日记2 小时前
【LVS入门宝典】LVS DR模式深度解析:直接路由(DR)的高性能秘诀,MAC地址欺骗与ARP隔离
linux·运维·负载均衡·lvs·arp
HappyGame022 小时前
Linux多进程编程(上)
linux
半梦半醒*2 小时前
在Linux中部署tomcat
java·linux·运维·服务器·centos·tomcat
半梦半醒*2 小时前
haproxy负载均衡
linux·运维·服务器·centos·负载均衡
Dovis(誓平步青云)3 小时前
《Linux 指令实战进阶:从终端新手到 shell 驾驭者的技术跃迁(第三篇)》
linux·运维·服务器
東雪蓮☆3 小时前
Redis 三种服务架构详解:主从复制、哨兵模式与集群
linux·运维·数据库·redis