Linux——Shell编程

发布于:2025-08-07 ⋅ 阅读:(26) ⋅ 点赞:(0)

Shell 基础介绍

Shell 的语言属性与本质

  • Shell 是一种程序设计语言。作为命令语言,它交互式解释和执行用户输入的命令或者自动地解释和执行预先设定好的一连串的命令;作为程序设计语言,它定义了各种变量和参数,并提供了许多在高级语言中才具有的控制结构,包括循环和分支。
  • Shell 是一个用 C 语言编写的程序,它是用户使用 Linux 的桥梁。
  • Shell 既是一种命令语言,又是一种程序设计语言。

Shell 编程与种类

  • Shell 编程跟 JavaScript、php 编程一样,只要有一个能编写代码的文本编辑器和一个能解释执行的脚本解释器就可以了。
  • Linux 的 Shell 种类众多,常见的有:
    • Bourne Shell(/usr/bin/sh 或 /bin/sh )
    • Bourne Again Shell(/bin/bash )
    • C Shell(/usr/bin/csh )
    • K Shell(/usr/bin/ksh )
    • Shell for Root(/sbin/sh )
  • 在一般情况下,人们并不区分 Bourne Shell 和 Bourne Again Shell,所以,像 #!/bin/sh,它同样也可以改为 #!/bin/bash 。
  • #! 告诉系统其后路径所指定的程序即是解释此脚本文件的 Shell 程序

Shell 脚本创建与代码解析

  • 打开文本编辑器 (可以使用 vi/vim 命令来创建文件),新建一个文件 test.sh ,扩展名为 sh(sh 代表 shell ),扩展名并不影响脚本执行,见名知意就好。
    输入一些代码,第一行一般是这样:
  • #!/bin/bash
    echo "Hello world !"

  • 代码解析
    • #! 是一个约定的标记,它告诉系统这个脚本需要什么解释器来执行,即使用哪一种 Shell 。
    • echo 命令用于向窗口输出文本。
  • 作为可执行程序运行脚本

    1. 保存代码为 test.sh ,进入脚本所在目录。
    2. chmod +x ./test.sh :赋予脚本执行权限
    3. ./test.sh :执行脚本(需用 ./ 指定当前目录,避免系统在 PATH 路径找命令)。
  • 作为解释器参数运行脚本
    直接调用 Shell 解释器执行脚本,如 /bin/sh test.sh (无需提前给脚本加执行权限 )。

2. Shell 基础语法范畴

属于 Shell 编程 “基础语法” 部分,涵盖:变量、参数传递、字符串、数组、运算符,以及 echo / printf(输出)、read(输入)、test(条件测试)等核心命令 。

简单说,这是教你 “怎么写、怎么跑” Shell 脚本 的基础操作指南,和 Shell 语法体系的前置知识 。

一、Shell 变量

变量是 Shell 编程的基本组成部分,用于存储数据,默认以字符串形式存储,无需显式声明类型。

定义变量
支持三种定义方式,赋值号=周围不能有空格:

  • variable=value
  • variable='value'
  • variable="value"
    命名规范:由数字、字母、下划线组成,必须以字母或下划线开头,不能使用 Shell 关键字。

示例:

url=http://www.shujia.com
echo $url
name='数加学院'
echo $name
author="shell编程"
echo $author

使用变量
在变量名前加$,推荐用${变量名}明确边界:

author="linux"
echo $author  # 输出:linux
echo ${author}  # 输出:linux

示例(明确边界):

skill="Java"
echo "I am good at ${skill}web"  # 输出:I am good at Javaweb

修改变量值
直接重新赋值,变量名前不加$

url="http://www.shujia.com"
echo ${url}  # 输出:http://www.shujia.com
url="http://www.shujia.com/shell/"
echo ${url}  # 输出:http://www.shujia.com/shell/

单引号与双引号的区别

  • 单引号' ':原样输出,不解析变量和命令。
  • 双引号" ":解析变量和命令。

示例:

url="http://www.shujia.com"
website1='数加学院网站:${url}'  # 单引号,不解析
website2="数加学院网站:${url}"  # 双引号,解析
echo $website1  # 输出:数加学院网站:${url}
echo $website2  # 输出:数加学院网站:http://www.shujia.com
  1. 命令结果赋值给变量

    • 方式 1:variable=命令 ``(反引号,不推荐)
    • 方式 2:variable=$(命令)(推荐,区分度高)
  2. 只读变量
    readonly定义,值不可修改:

  3. myUrl="http://www.shujia.com"
    readonly myUrl
    myUrl="http://www.shujia.com/new"  # 报错:无法修改只读变量

    删除变量
    unset,不能删除只读变量:

    myUrl="http://www.shujia.com"
    unset myUrl
    echo $myUrl  # 无输出
    二、Shell 传递参数

    执行脚本时可传递参数,脚本内通过$n获取($0为脚本文件名)。

  4. 基本用法
    示例:

#!/bin/bash
echo "shell传递参数实例!"
echo "执行的文件名:$0"
echo "第一个参数为:$1"
echo "第二个参数为:$2"
echo "第三个参数为:$3"

执行./test.sh 1 2 3,输出:

shell传递参数实例!
执行的文件名:./test.sh
第一个参数为:1
第二个参数为:2
第三个参数为:3

2

特殊字符处理参数

参数处理 说明
$# 传递到脚本的参数个数
$* 所有参数以单字符串显示(如 "$1 $2 ... $n")
$$ 脚本运行的当前进程 ID 号
$! 后台运行的最后一个进程的 ID 号
$@ $*类似,但加引号后返回每个参数(如 "$1" "$2" ... "$n")
$? 最后命令的退出状态(0 为无错误,非 0 为有错误)
  1. $*$@的区别

    • 相同点:均引用所有参数。
    • 不同点:双引号中,"$*"等价于 "1 2 3"(一个参数),"$@"等价于 "1" "2" "3"(三个参数)。
三、Shell 字符串

字符串是 Shell 中最常用的数据类型,支持单引号、双引号、无引号三种形式。

  1. 三种形式的区别

    形式 特点
    单引号' ' 任何字符原样输出,不解析变量和命令;不能包含单引号(即使转义)。
    双引号" " 解析变量和命令;可包含转义的双引号(\")。
    无引号 解析变量;不能包含空格(否则空格后内容被视为其他变量 / 命令)。
     

    示例:

  2. n=74
    str1=www.shujia.com$n  # 无引号,解析变量
    str2="shell \"script\" $n"  # 双引号,解析变量和转义
    str3='数加学院 $n'  # 单引号,不解析
    echo $str1  # 输出:www.shujia.com74
    echo $str2  # 输出:shell "script" 74
    echo $str3  # 输出:数加学院 $n

    获取字符串长度
    格式:${#string_name}
    示例:

  3. str="http://www.shujia.com"
    echo ${#str}  # 输出:21

    字符串拼接
    直接将字符串并排,无需运算符:

  4. name="Shell"
    url="http://www.shujia.com"
    str1=$name$url  # 无空格
    str2="$name $url"  # 双引号中可加空格
    str3=$name":"$url  # 可加其他字符
    echo $str1  # 输出:Shellhttp://www.shujia.com
    echo $str2  # 输出:Shell http://www.shujia.com
    echo $str3  # 输出:Shell:http://www.shujia.com

    字符串截取

    截取方式 格式 说明
    从左边指定位置 ${string: start :length} start为起始位置(从 0 计数),length为长度(省略则到末尾)。
    从右边指定位置 ${string: 0-start :length} start为起始位置(从 1 计数),length为长度(省略则到末尾)。
    从指定字符右边(第一次匹配) ${string#*chars} 忽略左边所有字符,截取chars右边内容。
    从指定字符右边(最后一次匹配) ${string##*chars} 忽略左边所有字符,截取最后一个chars右边内容。
    从指定字符左边(第一次匹配) ${string%*chars} 忽略右边所有字符,截取chars左边内容。
    从指定字符左边(最后一次匹配) ${string%%*chars} 忽略右边所有字符,截取最后一个chars左边内容。
url="http://www.shujia.com/index.html"
echo ${url#*://}  # 输出:www.shujia.com/index.html(截取://右边)
echo ${url##*/}  # 输出:index.html(截取最后一个/右边)
echo ${url%/*}  # 输出:http://www.shujia.com(截取最后一个/左边)
四、Shell 数组

Bash Shell 仅支持一维数组,初始化无需指定大小,下标从 0 开始。

  1. 定义数组
    格式:array_name=(元素1 元素2 ... 元素n)(元素用空格分隔)
    示例:

  2. my_array=(A B "C" D)

    读取数组元素
    格式:${array_name[index]}
    示例

  3. echo ${my_array[0]}  # 输出:A
    echo ${my_array[1]}  # 输出:B

    关联数组
    支持用字符串 / 整数作下标,需用declare -A声明:

  4. declare -A site  # 声明关联数组
    site["google"]="www.google.com"
    site["taobao"]="www.taobao.com"
    echo ${site["google"]}  # 输出:www.google.com

    获取所有元素
    ${array_name[@]}${array_name[*]}

  5. my_array=(A B C D)
    echo ${my_array[@]}  # 输出:A B C D

    获取数组长度
    ${#array_name[@]}${#array_name[*]}

  6. my_array=(A B C D)
    echo ${#my_array[@]}  # 输出:4

    获取数组长度
    ${#array_name[@]}${#array_name[*]}

  7. my_array=(A B C D)
    echo ${#my_array[@]}  # 输出:4
    五、Shell 运算符

    Shell 支持多种运算符,需通过expr等工具实现算术运算。

  8. 算术运算符(假定a=10b=20

    运算符 说明 示例
    + 加法 expr $a + $b → 30
    - 减法 expr $a - $b → -10
    * 乘法(需转义\* expr $a \* $b → 200
    / 除法 expr $b / $a → 2
    % 取余 expr $b % $a → 0
    = 赋值 a=$b → a=20
    == 相等(数字比较) [ $a == $b ] → false
    != 不相等(数字比较) [ $a != $b ] → true
     

    示例:

a=10; b=20
echo `expr $a + $b`  # 输出:30
  1. 关系运算符(仅支持数字,假定a=10b=20

    运算符 说明 示例
    -eq 等于 [ $a -eq $b ] → false
    -ne 不等于 [ $a -ne $b ] → true
    -gt 大于 [ $a -gt $b ] → false
    -lt 小于 [ $a -lt $b ] → true
    -ge 大于等于 [ $a -ge $b ] → false
    -le 小于等于 [ $a -le $b ] → true
  2. 布尔运算符

    运算符 说明 示例
    ! [ ! $a -eq $b ] → true
    -a [ $a -lt 100 -a $b -gt 15 ] → true
    -o [ $a -lt 5 -o $b -gt 100 ] → false
  3. 逻辑运算符

    运算符 说明 示例
    && 逻辑与 [[ $a -lt 100 && $b -gt 100 ]] → false
    ` ` 逻辑或 `[[ $a -lt 100 $b -gt 100 ]]` → true
  4. 字符串运算符(假定a="abc"b="efg"

    运算符 说明 示例
    = 字符串相等 [ $a = $b ] → false
    != 字符串不相等 [ $a != $b ] → true
    -z 字符串长度为 0 [ -z $a ] → false
    -n 字符串长度不为 0 [ -n "$a" ] → true
    $ 字符串不为空 [ $a ] → true
  5. 文件测试运算符

    运算符 说明 示例
    -b file 是否为块设备文件 [ -b $file ] → false
    -c file 是否为字符设备文件 [ -c $file ] → false
    -d file 是否为目录 [ -d $file ] → false
    -f file 是否为普通文件 [ -f $file ] → true
    -r file 是否可读 [ -r $file ] → true
    -w file 是否可写 [ -w $file ] → true
    -x file 是否可执行 [ -x $file ] → true
    -s file 是否非空(大小 > 0) [ -s $file ] → true
    -e file 是否存在(含目录) [ -e $file ] → true
六、echo 命令

用于输出字符串,支持多种格式控制。

  1. 基本用法

    • 显示普通字符串:echo "It is a test" 或 echo It is a test
    • 显示转义字符:echo "\"It is a test\"" → 输出:"It is a test"
    • 显示变量:结合read命令读取输入并输出:
#!/bin/sh
read name  # 从标准输入读取
echo "$name It is a test"
    • 执行后输入 "OK",输出:OK It is a test
  1. 控制换行

    • 换行:echo -e "OK!\nIt is a test"-e开启转义,\n换行)
      输出:
OK!
It is a test
    • 不换行:echo -e "OK! \cIt is a test"\c不换行)
      输出:OK! It is a test
  1. 输出定向到文件
    echo "内容" > file(覆盖)或 echo "内容" >> file(追加)

  2. 原样输出
    用单引号:echo '${name}' → 输出:${name}

  3. 显示命令结果
    用反引号:echo date`` → 输出当前日期时间

七、printf 命令

格式化输出,语法:printf format-string [arguments...]

  1. 格式替代符

    • %s:字符串;%d:整数;%c:字符;%f:小数。
    • 修饰符:%-10s(左对齐,占 10 字符)、%-4.2f(保留 2 位小数)。

    示例:

printf "%-10s %-8s %-4.2f\n" 姓名 性别 体重kg
printf "%-10s %-8s %-4.2f\n" 郭靖 男 66.1234
printf "%-10s %-8s %-4.2f\n" 杨过 男 48.6543

输出:

姓名        性别     体重kg
郭靖        男        66.12
杨过        男        48.65
  1. 转义序列

    序列 说明
    \a 警告字符(BEL)
    \b 后退
    \c 抑制结尾换行
    \n 换行
    \r 回车
    \t 水平制表符
    \\ 反斜杠
八、read 命令

读取键盘输入,语法:read [-options] [variables](无变量则存到REPLY)。

  1. 常用选项

    选项 说明
    -a array 赋值给数组(从下标 0 开始)
    -d delimiter delimiter为结束符(不含该字符)
    -n num 读取num个字符
    -p prompt 显示提示信息
    -s 静默模式(不显示输入,如密码)
    -t seconds 超时时间(秒)
  2. 实例

    • 读取多个输入:
read -p "Enter info > " name url age
echo "网站:$name, 网址:$url, 年龄:$age"
  • 输入 “数加 http://www.shujia.com 6”,输出:网站:数加, 网址:http://www.shujia.com, 年龄:6
  • 读取单个字符:
  • read -n 1 -p "Enter a char> " char
    echo $char  # 输入"1",输出:1
    九、test 命令

    检查条件是否成立,支持数值、字符、文件测试。

  • 数值测试

    表达式 说明
    test $a -eq $b a等于b
    test $a -ne $b a不等于b
    test $a -gt $b a大于b
    ... 同关系运算符
     

    示例:

  • num1=100; num2=100
    if test $num1 -eq $num2; then
      echo "相等"
    else
      echo "不等"
    fi  # 输出:相等

  • 字符串测试

    表达式 说明
    test $a = $b 字符串a等于b
    test $a != $b 字符串a不等于b
    test -z $a 字符串a长度为 0
    ... 同字符串运算符
  • 文件测试
    同文件测试运算符,示例:

  • file="test.sh"
    if test -f $file; then
      echo "是普通文件"
    fi  # 输出:是普通文件

  • 逻辑操作符

    • !:非;-a:与;-o:或。
      示例:test -f $file -a -r $file → 文件存在且可读。
  • 基本语法

  • 第三章节:Shell 流程控制

    一、if-else 语句
  • # 单分支
    if condition; then
      command1
      ...
    fi
    
    # 双分支
    if condition; then
      command1
    else
      command2
    fi
    
    # 多分支
    if condition1; then
      command1
    elif condition2; then
      command2
    else
      commandN
    fi

    判断方式

  • []if [ $a -gt $b ]; then(大于用-gt,小于用-lt
  • ((...))if (( a > b )); then(直接用> <
  • 示例:

  • a=10; b=20
    if (( a < b )); then
      echo "a 小于 b"
    fi  # 输出:a 小于 b
    二、for 循环

    语法:

  • for var in list; do
      command1
      ...
    done


    (list省略则用命令行参数)

     

    示例:

  • for loop in 1 2 3 4 5; do
      echo "值: $loop"
    done

    输出:

  • 值: 1
    值: 2
    值: 3
    值: 4
    值: 5
    三、while 语句

    用于重复执行命令,语法:

  • while condition; do
      command1
      ...
    done

    示例:

  • 计数输出(1-5):
  • int=1
    while [ $int -le 5 ]; do
      echo $int
      int=$((int+1))  # 自增
    done

    读取键盘输入

  • echo "按<CTRL-D>退出"
    while read FILM; do
      echo "$FILM 是好网站"
    done
    四、无限循环

    三种形式:

  • # 方式1
    while :; do
      command
    done
    
    # 方式2
    while true; do
      command
    done
    
    # 方式3
    for ((;;)); do
      command
    done
    五、until 循环

    与 while 相反,条件为true时停止,语法:

  • until condition; do
      command1
      ...
    done

    示例(输出 0-9):

  • a=0
    until [ ! $a -lt 10 ]; do  # 当a>=10时停止
      echo $a
      a=$((a+1))
    done
    六、case ... esac

    多分支选择,语法:

  • case 值 in
      模式1)
        command1
        ...
        ;;
      模式2)
        command2
        ...
        ;;
      *)  # 默认
        commandN
        ;;
    esac

    示例:

  • site="bigdata"
    case "$site" in
      "bigdata") echo "大数据" ;;
      "google") echo "Google" ;;
      *) echo "其他" ;;
    esac  # 输出:大数据
    七、跳出循环
  • break:跳出所有循环。
    示例:
  • while :; do
      read aNum
      if [ $aNum -gt 5 ]; then
        break  # 大于5则跳出
      fi
    done

    continue:跳出当前循环。
    示例:

  • while :; do
      read aNum
      if [ $aNum -gt 5 ]; then
        continue  # 大于5则跳过本次循环
      fi
    done

    第四章节:Shell 函数

    一、函数语法

    定义格式:

  • [function] funname() {
      action;
      [return int;]  # 可选,返回值0-255
    }

    示例:

  • # 无返回值
    hello() {
      echo "这是我的第一个函数"
    }
    hello  # 调用,输出:这是我的第一个函数
    
    # 有返回值
    add() {
      return $(($1 + $2))
    }
    add 2 3
    echo $?  # 输出:5(用$?获取返回值)
    二、函数参数

    函数内用$n获取参数($1第一个参数,$10需用${10})。

     

    示例:

  • funwithParam() {
      echo "第一个参数: $1"
      echo "第十个参数: ${10}"
      echo "参数总数: $#"
    }
    funwithParam 1 2 3 4 5 6 7 8 9 10 11  # 调用

    输出:

  • 第一个参数: 1
    第十个参数: 10
    参数总数: 11

    特殊字符同传递参数($#$*等)。

    第五章节:Shell 输入 / 输出重定向

    重定向用于改变命令的输入 / 输出源(默认终端)。

    一、重定向命令
    命令 说明
    command > file 输出重定向到file(覆盖)
    command < file 输入重定向到file
    command >> file 输出追加到file
    n > file 文件描述符n重定向到file
    n >> file 文件描述符n追加到file
    n>&m 合并输出文件mn
    n<&m 合并输入文件mn
    <<tag tag开始到tag结束的内容作为输入
     

    (文件描述符:0=stdin,1=stdout,2=stderr)

    二、输出重定向
  • 覆盖:command > file
    示例:who > userswho命令结果写入users
  • 追加:command >> file
    示例:echo "内容" >> users(添加到users末尾)
  • 三、输入重定向

    command < file(命令从file获取输入)
    示例:wc -l < users(统计users行数,不显示文件名)

    四、重定向深入
  • 重定向 stderr:command 2> file(错误输出到file
  • 合并 stdout 和 stderr:command > file 2>&1 或 command &> file
  • 五、/dev/null 文件

    写入内容被丢弃,用于 “禁止输出”:

  • 屏蔽 stdout:command > /dev/null
  • 屏蔽 stdout 和 stderr:command > /dev/null 2>&1
  • 同时重定向 stdin 和 stdout:command < infile > outfile(从infile读,输出到outfile

网站公告

今日签到

点亮在社区的每一天
去签到