Shell学习(1/6) 教程-变量

一、教程

Shell 是一个用 C 语言编写的程序,它是用户使用 Linux 的桥梁。Shell 既是一种命令语言,又是一种程序设计语言。
Shell 是指一种应用程序,这个应用程序提供了一个界面,用户通过这个界面访问操作系统内核的服务。

Shell 脚本

Shell 脚本(shell script),是一种为 shell 编写的脚本程序。
业界所说的 shell 通常都是指 shell 脚本,但读者朋友要知道,shell 和 shell script 是两个不同的概念。

常见的 Shell 类型:

  1. Bash (Bourne Again Shell):是最常见的 Linux 和 macOS 默认 Shell,功能强大且易用。
  2. sh (Bourne Shell):经典的 Unix Shell,许多其他 Shell 都是基于它扩展的。
  3. zsh (Z Shell):功能强大的 Shell,比 Bash 更加灵活,支持自动补全和更强的脚本功能。
  4. fish (Friendly Interactive Shell):注重易用性和交互性,提供了丰富的提示和补全功能。
  5. csh (C Shell):语法和 C 语言类似,曾在一些早期的 Unix 系统中广泛使用。

第一个shell脚本

1.使用 nano 创建脚本

  1. 打开终端。
  2. 输入以下命令来创建并编辑脚本:

nano myscript.sh
3. 输入您的脚本内容。例如
#!/bin/bash echo "Hello, World!"

  1. Ctrl + O 保存文件,然后按 Enter 确认文件名。
  2. Ctrl + X 退出编辑器。

2. 赋予脚本执行权限

chmod +x myscript.sh
使脚本变为可执行文件。

3. 运行脚本

如果脚本位于当前目录:

./myscript.sh

如果脚本不在当前目录,您需要提供脚本的完整路径:

/path/to/myscript.sh

4. 运行结果

Hello, World!

二、Shell 变量

在 Shell 编程中,变量是用于存储数据值的名称。
变量名的命名须遵循如下规则:

  • 只包含字母、数字和下划线: 变量名可以包含字母(大小写敏感)、数字和下划线 _,不能包含其他特殊字符。
  • 不能以数字开头: 变量名不能以数字开头,但可以包含数字。
  • 避免使用 Shell 关键字: 不要使用Shell的关键字(例如 if、then、else、fi、for、while 等)作为变量名,以免引起混淆。
  • 使用大写字母表示常量: 习惯上,常量的变量名通常使用大写字母,例如 PI=3.14。
  • 避免使用特殊符号: 尽量避免在变量名中使用特殊符号,因为它们可能与 Shell 的语法产生冲突。
  • 避免使用空格: 变量名中不应该包含空格,因为空格通常用于分隔命令和参数。

1. 使用变量

使用一个定义过的变量,只要在变量名前面加美元符号即可,如:

#!/bin/bash
my_name="xaye"
echo ${my_name}
echo $my_name

变量名外面的花括号是可选的,加不加都行,加花括号是为了帮助解释器识别变量的边界,和Kotlin类似。

2. 只读变量

使用 readonly 命令可以将变量定义为只读变量,只读变量的值不能被改变。

#!/bin/bash

myUrl="https://www.google.com"
readonly myUrl
myUrl="https://www.runoob.com"

运行脚本,结果如下:

./myscript.sh: line 4: myUrl: readonly variable

3. 删除变量

使用 unset 命令可以删除变量。语法:
unset variable\_name
变量被删除后不能再次使用。unset 命令不能删除只读变量。

#!/bin/sh

myUrl="https://www.runoob.com"
unset myUrl
echo $myUrl

执行将没有任何输出。

xaye@PS2022YZEUYRLD:/mnt/e/Android-NDK-C/sh$ ./myscript.sh

xaye@PS2022YZEUYRLD:/mnt/e/Android-NDK-C/sh$

4. 变量类型

4.1 字符串变量
存储字符或字符串,默认情况下 Shell 中的变量都被视为字符串类型。

name="Xaye"
greeting="Hello, ${name}!"
echo $greeting
  • 不需要声明类型。
  • 使用双引号可以防止空格或特殊字符被误解释。
  • 使用单引号禁止变量替换。

4.2 数组变量
用于存储多个值(下标从 0 开始)。
定义array=(value1 value2 value3)
访问元素echo ${array[0]} # 输出第一个元素
操作数组
获取所有元素: ${array[@]}${array[\*]}
获取数组长度: ${#array[@]}
示例

colors=("red" "green" "blue")
echo ${colors[1]}       # 输出 green
echo ${colors[@]}       # 输出 red green blue
echo ${#colors[@]}      # 输出 3

4.3 整数变量
用于存储和操作整数值(需要指定计算模式)。

num=42

算术运算:
使用 $((expression)) 进行整数运算。

num=$((5 + 10))
echo $num  # 输出 15

增加或减少:

num=$((num + 1))
echo $num  # 输出 16

注意:默认情况下,Shell 不支持浮点运算,可借助 bc 或其他工具实现。

4.4 环境变量
系统级变量,影响系统环境或子进程行为。
常见环境变量

  • $PATH:可执行文件的搜索路径。
  • $HOME:用户的主目录。
  • $USER:当前登录的用户名。
  • $SHELL:当前使用的 Shell 类型。

操作环境变量
查看当前环境变量:

    env

设置新的环境变量:

    export VAR="value"

查看某个变量:

    echo $VAR

4.5 特殊变量
Shell 内置的特殊变量,用于存储命令、脚本参数或运行状态信息。

  • 常见特殊变量
    • $0:当前脚本或命令名。
    • $1, $2, ...:命令行参数。
    • $@:所有参数(逐个分开)。
    • $\*:所有参数(作为一个字符串)。
    • $#:参数个数。
    • $?:上一个命令的退出状态。
    • $$:当前 Shell 的进程 ID。
    • $!:最近运行的后台任务的进程 ID。

4.6 总结

类型 说明 示例
字符串变量 存储字符或字符串,Shell 默认变量类型。 name="Alice"echo "Hello, $name!"
数组变量 存储多个值,支持索引访问及操作。 array=(val1 val2)echo ${array[0]}
整数变量 存储和操作整数,支持算术运算。 num=$((5 + 3))echo $num
环境变量 系统级变量,影响系统环境或子进程。 $PATH, $HOME, export VAR=value
特殊变量 内置变量,用于存储命令、参数及状态信息。 $@, $\*, $?, $$, $!

5. Shell 字符串

字符串是shell编程中最常用最有用的数据类型(除了数字和字符串,也没啥其它类型好用了),字符串可以用单引号,也可以用双引号,也可以不用引号。
5.1 单引号
内容完全原样输出,变量或特殊字符不会被解析。

str='Hello $USER'
echo $str  # 输出:Hello $USER

5.2 双引号
支持变量和特殊字符的解析。

name="Xaye"
greeting="Hello, $name!"
echo $greeting  # 输出:Hello, Xaye!

5.3 拼接字符串

name="Xaye"
full_greeting="Hello, "$name"!"
echo $full_greeting  # 输出:Hello, Xaye!

5.4 获取字符串长度
使用 ${#变量名} 获取字符串的长度:

str="Hello, World"
echo ${#str} # 输出:12

5.5 提取字符串
使用 ${变量名:起始位置:长度} 提取子字符串:

str="Hello, World"
echo ${str:7:5}  # 输出:World

起始位置从 0 开始;如果只指定起始位置,则提取到字符串末尾。

echo ${str:7}  # 输出:World

5.6 查找字符串
使用 expr index 或内置方法查找子字符串的位置。
示例 1: expr 方法:

str="Hello, World"
echo $(expr index "$str" W)  # 输出:8

示例 2:内置查找:

str="Hello, World"
echo ${str%%W*}  # 输出:Hello, 

6. Shell 数组

bash支持一维数组(不支持多维数组),并且没有限定数组的大小。
类似于 C 语言,数组元素的下标由 0 开始编号。获取数组中的元素要利用下标,下标可以是整数或算术表达式,其值应大于或等于 0。
6.1 定义数组
用括号 () 定义数组,数组元素用空格分隔。

arr=(value1 value2 value3)

单独赋值:可以为特定下标的元素单独赋值。

arr[0]="value1"
arr[1]="value2"
arr[2]="value3"

6.2 读取数组
读取单个元素:通过下标访问数组元素(下标从 0 开始)。

echo ${arr[0]}  # 输出:value1

读取所有元素:使用 ${数组名[@]}${数组名[\*]}

echo ${arr[@]}  # 输出:value1 value2 value3
运行:
xaye@PS2022YZEUYRLD:/mnt/e/Android-NDK-C/sh$ ./myscript.sh
value1 value2 value3

6.3 获取数组的长度
语法${#数组名[@]}

echo ${#arr[@]}  # 输出:3

示例代码

# 定义数组
fruits=("apple" "banana" "cherry")

# 读取单个元素
echo ${fruits[1]}  # 输出:banana

# 读取所有元素
echo ${fruits[@]}  # 输出:apple banana cherry

# 获取数组长度
echo ${#fruits[@]}  # 输出:3

7. Shell 注释

7.1 单行注释
使用 # 开头,表示该行的内容是注释,不会被执行。

# 这是一个单行注释
echo "Hello, World!"  # 输出内容

7.2 多行注释
Shell 不支持原生的多行注释,但可以通过以下方法实现:

  • 连续使用 #** 注释多行**:
# 这是第一行注释
# 这是第二行注释
# 这是第三行注释
  • 使用 : ' ' : + 空格 + 单引号 或 : <<EOF ... EOF** 的方法**:
: '
这是第一行注释
这是第二行注释
这是第三行注释
'
<<EOF
这是第一行注释
这是第二行注释
这是第三行注释
EOF