Shell
Shell简介
Shell 是一种用户与操作系统之间的交互界面,它解释并执行用户输入的命令,通常用于管理操作系统、执行脚本或自动化任务。Shell 是操作系统中一个非常重要的组件,尤其是在类Unix系统(如Linux、macOS)中。下面是Shell的概念和功能的详细解释:
Shell的定义
Shell 是操作系统中的一个命令行解释器,主要功能是:
- 接收用户命令,然后将这些命令传递给操作系统内核去执行。
- 脚本解释器,可以执行由用户编写的一系列命令脚本(Shell脚本)。
Shell的名字来自它在操作系统中的作用:它包裹着内核(kernel),为用户提供一个与操作系统核心交互的接口。
Shell解释器:
是操作系统中的一个命令行程序,用于解释并执行用户输入的命令和脚本。Shell 作为用户与操作系统内核之间的桥梁,可以处理用户输入的命令、脚本文件,并与操作系统交互。
在 Linux、Unix 以及 macOS 等类 Unix 系统中,常见的 Shell 解释器包括:
- Bash (Bourne Again Shell)
· 最流行的 Shell,功能强大,支持复杂的脚本编写。
· 通常默认位于 /bin/bash 路径。
- sh (Bourne Shell)
· 是 Unix 最早的 Shell,简单高效,但功能较少。
· 兼容性强,用于运行许多简单的 Shell 脚本
- zsh (Z Shell)
· 是一种增强版的 Shell,提供更丰富的功能和用户友好的特性,如自动补全、强大的配置工具。
- csh (C Shell)
- ksh (Korn Shell)
· 兼具 Bourne Shell 和 C Shell 的优点,提供更丰富的编程功能。
最常用的是 Bash,它是大多数 Linux 系统的默认 Shell。
Shell解释器的功能:
1.解释命令:Shell 解释器可以执行用户在命令行中输入的命令,比如 ls、cd、echo 等。
2.执行脚本:Shell 可以读取并执行一系列预定义的命令,存储在文件中的命令被称为 Shell 脚本。
3.流程控制:支持条件判断(if)、循环(for、while)、函数等编程结构。
4.环境管理:Shell 解释器可以管理环境变量,如 PATH、HOME 等。
5.命令替换:支持将命令的输出作为另一个命令的输入。
Shell脚本
(1).第一个shell脚本:
打开文本编辑器(可以使用 vi/vim 命令来创建文件),新建一个文件 test.sh,扩展名为 sh(sh代表shell),扩展名并不影响脚本执行,见名知意就好,如果你用 php 写 shell 脚本,扩展名就用 php 好了。
实例:
#!/bin/bash
echo “hello word !”
#! 是一个约定的标记,它告诉系统这个脚本需要什么解释器来执行,即使用哪一种 Shell。
echo 命令用于向窗口输出文本。
运行 Shell 脚本有两种方法:
- 作为可执行程序
chmod +x ./test.sh #使脚本具有执行权限
./test.sh #执行脚本
2、作为解释器参数
bash test.sh
(2).sh和php的区别
打开文本编辑器(可以使用 vi/vim 命令来创建文件),新建一个文件 test.sh,扩展名为 sh(sh代表shell),扩展名并不影响脚本执行,见名知意就好,如果你用 php 写 shell 脚本,扩展名就用 php 好了。
实例:sh(Shell Script)的语法相对简单,很多命令直接调用系统命令。Shell 脚本通常以.sh结尾。
#!/bin/bash
echo "Hello World !"
实例:PHP是一种类似C语言的脚本语言,语法更结构化,支持面向对象编程。PHP文件通常以.php结尾。
<?php
echo "Hello, World!";
?>
运行shell脚本有两种方法:
1、作为可执行程序
将上面的代码保存为 test.sh,并 cd 到相应目录:
chmod +x ./test.sh #使脚本具有执行权限
./test.sh #执行脚本
注意,一定要写成 ./test.sh,而不是 test.sh,运行其它二进制的程序也一样,直接写 test.sh,linux 系统会去 PATH 里寻找有没有叫 test.sh 的,而只有 /bin, /sbin, /usr/bin,/usr/sbin 等在 PATH 里,你的当前目录通常不在 PATH 里,所以写成 test.sh 是会找不到命令的,要用 ./test.sh 告诉系统说,就在当前目录找。
2、作为解释器参数
这种运行方式是,直接运行解释器,其参数就是 shell 脚本的文件名,如:
bash test.sh
php test.php (确定安装PHP后执行)
这种方式运行的脚本,不需要在第一行指定解释器信息,写了也没用。
Shell结构
在Shell脚本中,结构化的编程方式让脚本能够进行更复杂的操作,支持逻辑判断、循环和函数调用等。以下是Shell脚本中常用的结构:
1. 条件判断结构
1.1 `if` 语句
Shell中的 `if` 语句用于根据条件执行不同的代码块。
基本语法:
if [ condition ]; then
# 条件为真时执行的代码
elif [ another_condition ]; then
# 另一个条件为真时执行的代码
else
# 以上条件都为假时执行的代码
fi
示例:
#!/bin/bash
num=5
if [ $num -gt 10 ]; then
echo "Number is greater than 10"
elif [ $num -eq 5 ]; then
echo "Number is equal to 5"
else
echo "Number is less than 10"
fi
1.2 `case` 语句
`case` 语句适用于多条件判断,可以替代多重 `if-elif` 语句。
基本语法:
case variable in
pattern1)
# 匹配 pattern1 时执行的代码
;;
pattern2)
# 匹配 pattern2 时执行的代码
;;
*)
# 其他情况执行的代码
;;
esac
示例:
#!/bin/bash
fruit="apple"
case $fruit in
"apple")
echo "You selected apple"
;;
"banana")
echo "You selected banana"
;;
*)
echo "Unknown fruit"
;;
esac
2. 循环结构
2.1 `for` 循环
`for` 循环用于遍历列表或范围的元素。
基本语法:
for var in list; do
# 使用 $var 执行的代码
done
示例:
#!/bin/bash
for i in 1 2 3 4 5; do
echo "Number: $i"
done
2.2 `while` 循环
`while` 循环会在指定条件为真时反复执行某段代码。
基本语法:
while [ condition ]; do
# 条件为真时执行的代码
done
示例:
#!/bin/bash
counter=1
while [ $counter -le 5 ]; do
echo "Counter: $counter"
((counter++))
done
2.3 `until` 循环
`until` 循环与 `while` 循环相反,它在条件为假时执行代码,直到条件为真。
基本语法:
until [ condition ]; do
# 条件为假时执行的代码
done
示例:
#!/bin/bash
counter=1
until [ $counter -gt 5 ]; do
echo "Counter: $counter"
((counter++))
done
3. 函数结构
函数是Shell脚本中一组命令的集合,函数定义后可以多次调用。
3.1 定义函数
基本语法:
function function_name {
# 函数体
}
示例:
#!/bin/bash
function greet {
echo "Hello, $1!"
}
greet "Alice" # 调用函数,传递参数
3.2 返回值
函数可以通过 `return` 返回一个退出状态码。注意,Shell函数无法直接返回值,只能通过变量或输出来传递值。
示例:
#!/bin/bash
function add {
local sum=$(( $1 + $2 ))
echo $sum # 输出结果
}
result=$(add 3 4)
echo "Sum: $result"
```
4. 逻辑运算符
Shell支持多种逻辑运算符,用于条件判断和组合。
4.1算术比较运算符:
- `-eq`:等于
- `-ne`:不等于
- `-lt`:小于
- `-le`:小于或等于
- `-gt`:大于
- `-ge`:大于或等于
示例:
if [ $num -gt 10 ]; then
echo "Number is greater than 10"
fi
4.2 字符串比较运算符:
- `=`:字符串等于
- `!=`:字符串不等于
- `-z`:字符串为空
- `-n`:字符串非空
示例:
str="hello"
if [ -n "$str" ]; then
echo "String is not empty"
fi
4.3 **逻辑运算符**:
- `&&`:逻辑与(and)
- `||`:逻辑或(or)
示例:
if [ $num -gt 5 ] && [ $num -lt 15 ]; then
echo "Number is between 5 and 15"
fi
5. 文件测试操作符
Shell可以通过一些特殊操作符来测试文件或目录的属性。
常用的文件测试操作符:
- `-e file`:文件是否存在
- `-f file`:是否为普通文件
- `-d directory`:是否为目录
- `-r file`:文件是否可读
- `-w file`:文件是否可写
- `-x file`:文件是否可执行
示例:
#!/bin/bash
file="test.txt"
if [ -e $file ]; then
echo "File exists"
else
echo "File does not exist"
fi
6. 其他控制结构
6.1 `break` 和 `continue`
- `break` 用于立即退出循环。
- `continue` 用于跳过当前循环,进入下一次迭代。
示例:
#!/bin/bash
for i in {1..10}; do
if [ $i -eq 5 ]; then
break # 在 i=5 时退出循环
fi
echo "i: $i"
done
6.2 `select` 语句
`select` 语句用于创建菜单供用户选择,它会循环等待用户输入。
基本语法:
select option in list; do
# 使用 $option 执行的代码
done
示例:
#!/bin/bash
select fruit in apple banana cherry; do
echo "You selected $fruit"
break # 结束 select 循环
done
Shell基础命令
Bash
Bash (Bourne Again Shell) 是一种常见的 Unix shell 和命令语言解释器,常用于 Linux 和 macOS 等操作系统中。Bash 是 GNU 操作系统的一部分,它是 Bourne shell (sh) 的增强版本,提供了更强大的编程功能和交互特性。
Bash 的主要功能包括:
- 命令解释器:允许用户输入命令并将其传递给操作系统执行。
- 脚本编写:Bash 可以用于编写脚本,自动执行任务,例如批量处理文件、定时任务和系统管理任务。
- 环境管理:Bash 提供了对环境变量的管理,如 PATH、HOME 等变量的设置和访问。
- 文件系统导航:Bash 提供了命令来浏览、查看、修改文件和目录。
常用的 Bash 命令包括:
- ls:列出当前目录下的文件和目录。
- cd:切换工作目录。
- cp:复制文件或目录。
- mv:移动或重命名文件。
- rm:删除文件或目录。
- echo:打印输出文本或变量内容。
- cat:查看文件内容。
- grep:搜索文件中的文本。
- chmod:修改文件权限。
- export:设置环境变量。
Bash 还支持条件判断、循环、函数等编程语言特性,使其非常适合用于系统管理和自动化脚本开发。
date
一、date命令介绍
1.date语法:
date [选项] [+格式]
其中,选项 是可选的命令选项,用于控制 date 命令的行为;+格式 是可选的日期和时间格式,用于指定输出的日期和时间的格式。
2.常用选项:
-d:指定要显示的日期和时间,可以是具体的日期和时间字符串,也可以是表示时间间隔的字符串。
-u:显示协调世界时(UTC)。
-R:以 RFC 2822 格式输出日期和时间。
-I:以 ISO 8601 格式输出日期和时间。
-s:设置系统的日期和时间。
-r:显示指定文件的最后修改时间。
3.常用的data命令格式:
下面是一些常用的 date 命令格式的说明:
%Y:四位数的年份。
%m:两位数的月份(01-12)。
%d:两位数的日期(01-31)。
%H:两位数的小时(00-23)。
%M:两位数的分钟(00-59)。
%S:两位数的秒数(00-59)。
%A:完整的星期几名称(例如:Sunday)。
%a:缩写的星期几名称(例如:Sun)。
%B:完整的月份名称(例如:January)。
%b:缩写的月份名称(例如:Jan)。
二、date命令示例用法
1. date命令的示例用法
显示当前的日期和时间:
date
(2) 显示指定格式的日期和时间
显示当前日期和时间的指定格式:
date +"%Y-%m-%d %H:%M:%S"
(3) 显示指定日期和时间
显示指定日期和时间的格式:
date -d "2023-12-14 17:39:08" +"%Y-%m-%d %H:%M:%S"
(4) 设置系统的日期和时间
设置系统的日期和时间为指定的日期和时间:
(5) 显示目录或文件的最后修改时间
显示指定文件的最后修改时间:
date -r filename
以上只是 date 命令的一些常见用法,还有更多选项和参数可以根据具体需求来使用。可以通过 man date 命令或 date --help 命令来查看完整的选项和参数列表。
2. date命令的日期计算
date 命令支持对日期和时间进行计算和调整。可以使用 -d 选项指定要计算的日期和时间,以及要添加或减去的时间间隔。
时间单位:
seconds/second
minutes/minute
hours/hour
days/day
weeks/week
months/month
years/year
(1) 计算指定日期一个月后的日期
date -d "2023-11-15 + 1 month"
(2) 计算指定日期一个小时后的时间
date -d "+ 1 hour"
(3) 计算当前日期三天后的时间
计算当前日期三天后的时间,并指定格式。
3. date命令的相对日期表示
date -d 命令还支持使用相对于当前日期的表示方式来指定日期。以下是一些常见的相对日期表示方式:
“X seconds ago” :表示 X 秒前的日期。
“X minutes ago” :表示 X 分钟前的日期。
“X hours ago” :表示 X 小时前的日期。
“X days ago” :表示 X 天前的日期。
“X weeks ago” :表示 X 周前的日期。
“X months ago” :表示 X 个月前的日期。
“X years ago” :表示 X 年前的日期。
其中,X 是一个整数,用于指定偏移的数量。
(1) 计算当前日期一个月前的日期
计算当前日期一个月前的日期,并指定格式。
date -d "1 months ago" +"%Y-%m-%d %H:%M:%S"
(2) 计算当前日期一个小时前的时间
计算当前日期一个小时前的时间,并指定格式。
date -d "1 hours ago" +"%Y-%m-%d %H:%M:%S"
history
1.显示命令历史:
(1). history
(2). 这个命令会列出当前用户会话中执行过的命令列表,通常包括命令编号。
2. 显示指定数量的最近命令:
(1). history [number]
(2). 例如,history 10 会显示最近的 10 条命令。
3. 重复执行历史中的命令:
(1)![number]
(2)例如,!10 会执行历史中编号为 10 的命令。
4. 搜索命令历史:
(1)history | grep [keyword]
(2)这个命令会搜索包含特定关键字的命令。例如,history | grep ls 会显示所有包含 ls 的命令。
5. 清空命令历史:
(1)history -c
(2)这个命令会清空当前会话的命令历史记录。
6. 保存命令历史到文件:
(1)history > history.txt
(2)这个命令会将命令历史保存到一个文本文件中。
7. 从文件中读取命令历史:
(1)history -r history.txt
(2)这个命令会从指定文件中读取并添加命令到当前会话的历史记录中。
8. 使用命令历史进行快速编辑和重用 :
(1)在很多 shell 环境中,可以使用上下方向键来浏览和选择历史命令进行重用。
!重复执行命令
chattr:改变文件属性
chattr命令的功能说明
chattr命令用于改变文件属性。这项指令可改变存放在ext2文件系统上的文件或目录属性,这些属性共有以下8种模式:
- a:让文件或目录仅供附加用途。
- b:不更新文件或目录的最后存取时间。
- c:将文件或目录压缩后存放。
- d:将文件或目录排除在倾倒操作之外。
- i:不得任意更动文件或目录。
- s:保密性删除文件或目录。
- S:即时更新文件或目录。
- u:预防意外删除。
chattr命令的语法格式
chattr [ -RVf ] [ -v version ] [ mode ] files...
chattr [-RV] [-v<版本编号>] [+/-/=<属性>] [文件或目录...]
chattr命令的选项说明
chattr 参数有几个,表1为 chattr 命令的参数及说明:
表1: chattr命令的参数及说明
参数选项 | 解释说明 |
-R | 递归处理,将指定目录下的所有文件及子目录一并处理。 |
-v<版本编号> | 设置文件或目录版本。 |
-V | 显示指令执行过程。 |
+<属性> | 开启文件或目录的该项属性。 |
-<属性> | 关闭文件或目录的该项属性。 |
=<属性> | 指定文件或目录的该项属性。 |
chattr命令的实践操作
范例1: 用chattr命令防止系统中某个关键文件被修改:
- [root@oldboyedu ~]# chattr +i /etc/resolv.conf
- [root@oldboyedu ~]# lsattr /etc/resolv.conf <-->lsattr显示文件属性(后面会讲)
- ----i-------- /etc/resolv.conf
- [root@oldboyedu ~]# chattr +i /etc/passwd #<==锁定文件不能删除,不能修改
- [root@oldboyedu ~]# lsattr /etc/passwd
- ----i----------- /etc/passwd
- [root@oldboyedu ~]# lsattr /etc/hosts
- ---------------- /etc/hosts
- [root@oldboyedu ~]# cp /etc/passwd{,.ori}
- [root@oldboyedu ~]# rm -f /etc/passwd
- rm: cannot remove ‘/etc/passwd’: Operation not permitted
- [root@oldboyedu ~]# echo ddd > /etc/passwd
- -bash: /etc/passwd: Permission denied
- [root@oldboyedu ~]# useradd littleboy
- useradd: cannot open /etc/passwd
- [root@oldboyedu ~]chattr -i /etc/passwd #<==解锁文件。
范例2: 让某个文件只能往里面追加数据,但不能删除,适用于各种日志文件:
- [root@oldboyedu ~]# chattr +a oldboy.txt
- [root@oldboyedu ~]# rm -f oldboy.txt
- rm: cannot remove ‘oldboy.txt’: Operation not permitted
- [root@oldboyedu ~]# echo dddd >>oldboy.txt
- [root@oldboyedu ~]# echo dddd >>oldboy.txt
lsattr:显示文件属性
lsattr命令的功能说明
lsattr命令用于显示文件属性。用chattr执行改变文件或目录的属性,可执行lsattr指令查询其属性。
lsattr命令的语法格式
lsattr [ -RVadv ] [ files... ]
lsattr [-adlRvV] [文件或目录...]
lsttr命令的选项说明
lsattr 参数有几个,表1为 lsattr 命令的参数及说明:
表1: lsattr命令的参数及说明
参数选项 | 解释说明 |
-a | 显示所有文件和目录,包括以"."为名称开头字符的额外内建,现行目录"."与上层目录".."。 |
-d | 显示,目录名称,而非其内容。 |
-l | 此参数目前没有任何作用。 |
-R | 递归处理,将指定目录下的所有文件及子目录一并处理。 |
-v | 显示文件或目录版本。 |
-V | 显示版本信息。 |
lsattr命令的实践操作
范例1: 用chattr命令防止系统中某个关键文件被修改,然后用lsattr查看
- [root@oldboyedu ~]# chattr +i /etc/passwd #<==锁定文件不能删除,不能修改
- [root@oldboyedu ~]# lsattr /etc/passwd
- ----i----------- /etc/passwd
- [root@oldboyedu ~]# lsattr /etc/hosts
- ---------------- /etc/hosts
alias和unalias命令
alias 用于设置指令的别名,用户可利用 alias,自定指令的别名。
它可以使您以一种更简单和易于记忆的方式执行命令,而不必每次都键入完整的命令。
若仅输入 alias,则可列出目前所有的别名设置。
alias 的效果仅在该次登入的操作有效,若想要每次登入都生效,可在 .profile 或 .cshrc 中设定指令的别名。
语法
alias[别名]=[指令名称]
参数:
若不加任何参数,则列出目前所有的别名设置。
实例:
1、创建别名:
alias ll='ls -alF'
此命令创建一个名为 ll 的别名,用于显示当前目录下所有文件和目录的详细列表。
2、显示别名:
alias
此命令将显示当前系统上所有的别名及其相应的命令。
删除别名:
unalias ll
此命令将删除名为 ll 的别名。
3、以 root 权限执行命令:
alias sudo='sudo '
此命令将创建一个名为 sudo 的别名,以便您可以通过在命令前加上 sudo 来以 root 权限执行命令。
注意:在命令末尾有一个空格,这是因为如果没有空格,则无法正确识别以root权限执行的命令。
4、向历史记录中添加时间戳:
alias history='history | awk '"'"'{CMD="date +\"[%Y-%m-%d %H:%M:%S]\""; print CMD " " $0 }'"'"' | cut -c 29-'
此命令将创建一个名为 history 的别名,它会在您执行历史记录命令时添加时间戳。
注意:此命令中的单引号内部有多个单引号和双引号,需要进行正确的转义。
5、启用颜色输出
在 alias 命令中使用 "--color=auto" 参数可以让该命令在支持颜色输出的终端上自动启用颜色输出,从而提高命令行的可读性。例如:
alias ls='ls --color=auto'
这个命令将创建一个简化的 ls 命令,它将自动启用颜色输出。
unalias 用于删除别名
语法:
unalias [-a] [别名]
参数:
-a 删除全部的别名。
实例:
删除别名
[root@runoob.com ~]# alias lx //显示别名
alias lx='ls'
[root@runoob.com ~]# unalias lx //删除别名
[root@runoob.com ~]# lx
-bash: lx: command not found
输入、输出重定向
输入、输出重定向:
- 输入重定向 (<): 从文件读取输入。
语法:
command < inputfile
- 输出重定向 (>): 将输出写入文件。
语法:
command > outputfile
- 追加输出 (>>): 将输出追加到文件末尾。
语法:
command >> outputfile
env
env:显示当前环境变量或运行命令在指定的环境中。
env
env VAR=value command
set
set: 设置Shell选项或显示当前的Shell变量。
set
set VAR=value
cut
cut: 从每行中提取指定的列或字段。
cut -d ':' -f 1 /etc/passwd
sort
sort: 对输入进行排序。
sort filename
wc
wc: 统计字数、行数和字符数。
wc filename
uniq
uniq: 去除重复的行。
uniq filename
tree
tree: 以树状图展示目录结构(需安装)。
tree directory
tr
tr: 字符替换或删除。
echo "hello" | tr 'a-z' 'A-Z'
split
split: 将文件分割为若干部分。
split -l 1000 filename
Shell 变量
在Shell脚本中,变量用于存储和操作数据。
注意,变量名和等号之间不能有空格,这可能和你熟悉的所有编程语言都不一样。同时,变量名的命名须遵循如下规则:
- 只包含字母、数字和下划线: 变量名可以包含字母(大小写敏感)、数字和下划线 _,不能包含其他特殊字符。
- 不能以数字开头: 变量名不能以数字开头,但可以包含数字。
- 避免使用 Shell 关键字: 不要使用Shell的关键字(例如 if、then、else、fi、for、while 等)作为变量名,以免引起混淆。
- 使用大写字母表示常量: 习惯上,常量的变量名通常使用大写字母,例如 PI=3.14。
- 避免使用特殊符号: 尽量避免在变量名中使用特殊符号,因为它们可能与 Shell 的语法产生冲突。
- 避免使用空格: 变量名中不应该包含空格,因为空格通常用于分隔命令和参数。
在Shell脚本中,**变量**用于存储和操作数据。变量的使用方式与大多数编程语言类似,但也有其独特之处。下面是有关Shell变量的基本知识和常见用法:
1. 定义变量
在Shell中,定义变量时不需要使用数据类型。只需将值赋给变量即可,且赋值时**等号两侧不能有空格**。
name="Alice"
number=42
2. 引用变量
引用变量时需要在变量名之前加上 `$` 符号。
echo $name
echo $number
也可以使用大括号 `{}` 来清晰界定变量名,尤其是在变量与其他字符相邻时:
echo "My name is ${name}."
3. 环境变量
环境变量在Shell中是全局的,能够被系统和所有的子进程访问。常见的环境变量有 `PATH`、`HOME` 等。
- 查看环境变量:
echo $PATH
echo $HOME
- 设置环境变量:
使用 `export` 命令将变量设置为环境变量:
export MY_VAR="Hello"
echo $MY_VAR
4. 读取用户输入
使用 `read` 命令可以从用户输入中读取值,并将其存储在变量中:
echo "Enter your name:"
read user_name
echo "Hello, $user_name!"
```
5. 命令替换
可以将命令的输出赋值给变量,方法是在反引号 `` `command` `` 或 `$(command)` 中包含命令。
current_time=$(date)
echo "The current time is $current_time."
6. 特殊变量
Shell中还有一些内置的特殊变量,常用于脚本处理参数和状态。
$0: 当前脚本的名称。
$1, $2, ..., $n: 传递给脚本或函数的参数。
$#: 传递给脚本或函数的参数个数。
$@: 传递给脚本的所有参数(分别引用)。
$*: 传递给脚本的所有参数(作为一个整体引用)。
$$: 当前Shell进程的PID(进程ID)。
$?: 上一个命令的退出状态(0表示成功,非0表示失败)。
echo "Script name: $0"
echo "First argument: $1"
echo "Number of arguments: $#"
7. 默认值与变量检查
可以为变量设置默认值,以防变量未被赋值时出现错误。
${variable:-default}: 如果变量未定义,则使用默认值。
name=${name:-"Guest"}
echo "Hello, $name"
${variable:=default}: 如果变量未定义,则赋予其默认值。
name=${name:="Guest"}
echo "Hello, $name"
8. 删除变量
可以使用 `unset` 删除变量,使其不再有效。
unset name
9. 示例脚本
下面是一个简单的Shell脚本示例,展示了变量的定义、引用、以及环境变量的使用:
#!/bin/bash
# 定义变量
greeting="Hello"
name="John"
# 输出变量
echo "$greeting, $name!"
# 读取用户输入
echo "Enter your age:"
read age
echo "You are $age years old."
# 使用命令替换
current_time=$(date)
echo "Current time: $current_time"
# 设置并使用环境变量
export MY_VAR="Some value"
echo "Environment variable MY_VAR: $MY_VAR"
这是使用变量的基本方法,Shell变量在自动化脚本和系统管理中非常强大。
Shell数组
在Shell脚本中,数组是一种用于存储多个值的数据结构。不同于大多数编程语言,Bash(和其他Shell)的数组是一维的,可以使用整数下标来访问数组元素。
1.定义数组
在Shell中,数组可以通过两种方式定义:
-
- 使用括号定义数组
#!/bin/bash
my_array=(A B "C" D)
-
- 单独定义数组元素
你也可以为数组中的每个元素单独赋值:
#!/bin/bash
array_name[0]=value0
array_name[1]=value1
array_name[2]=value2
2. 读取数组元素
读取数组元素值的一般格式是:
${array_name[index]}
实例:
#!/bin/bash
my_array=(A B "C" D)
echo "第一个元素为: ${my_array[0]}"
echo "第二个元素为: ${my_array[1]}"
echo "第三个元素为: ${my_array[2]}"
echo "第四个元素为: ${my_array[3]}"
输出结果
3. 访问所有数组元素
使用 @ 或 * 可以获取数组中的所有元素,例如:
实例:
#!/bin/bash
my_array[0]=A
my_array[1]=B
my_array[2]=C
my_array[3]=D
echo "数组的元素为: ${my_array[*]}"
echo "数组的元素为: ${my_array[@]}"
输出结果
4. 获取数组的长度
使用 ${#array[@]} 来获取数组的长度,即数组中元素的个数。
实例:
#!/bin/bash
my_array[0]=A
my_array[1]=B
my_array[2]=C
my_array[3]=D
echo "数组元素个数为: ${#my_array[*]}"
echo "数组元素个数为: ${#my_array[@]}"
输出结果:
5.关联数组
关联数组使用 declare -A array_name
-A 选项就是用于声明一个关联数组。
关联数组的键是唯一的。
以下实例我们创建一个关联数组 site,并创建不同的键值:
实例:
declare -A site=(["google"]="www.google.com" ["runoob"]="www.runoob.com" ["taobao"]="www.taobao.com")
我们也可以先声明一个关联数组,然后再设置键和值:
实例:
declare -A site
site["google"]="www.google.com"
site["runoob"]="www.runoob.com"
site["taobao"]=www.taobao.com
也可以在定义的同时赋值:
访问关联数组元素可以使用指定的键,格式如下:
array_name["index"]
以下实例我们通过键来访问关联数组的元素:
实例:
declare -A site
site["google"]="www.google.com"
site["runoob"]="www.runoob.com"
site["taobao"]="www.taobao.com"
echo ${site["runoob"]}
输出结果
Shell 传递参数
我们可以在执行 Shell 脚本时,向脚本传递参数,脚本内获取参数的格式为 $n,n 代表一个数字,1 为执行脚本的第一个参数,2 为执行脚本的第二个参数。
1.1 位置参数
位置参数用于访问传递给脚本的参数:
- $0:脚本名称
- $1:第一个参数
- $2:第二个参数
- $3:第三个参数
- ...,以此类推。
实例:
#!/bin/bash
echo "Shell 传递参数实例!";
echo "执行的文件名:$0";
echo "第一个参数为:$1";
echo "第二个参数为:$2";
echo "第三个参数为:$3";
输出结果
1.2 参数个数:$#
$# 表示传递给脚本的参数个数。
#!/bin/bash
echo "Number of arguments passed: $#"
1.3 所有参数:$* 和 $@
$*:表示所有参数,作为一个字符串传递(所有参数会合并成一个字符串)。
$@:表示所有参数,保留参数的独立性(每个参数保持独立)。
#!/bin/bash
echo "All arguments using \$*: $*"
echo "All arguments using \$@: $@"
输出结果
区别:
如果加引号 ", $* 会将所有参数作为单一的参数传递,而 $@ 保留各个参数。
for arg in "$*"; do
echo $arg # 只会输出一行包含所有参数
done
for arg in "$@"; do
echo $arg # 会输出每个参数一行
done
2.1 带默认值的参数
有时候,你可能希望参数有默认值。可以通过简单的条件语句实现。
实例:
#!/bin/bash
name=${1:-"Guest"} # 如果没有传递第一个参数,则使用 "Guest" 作为默认值
echo "Hello, $name!"
输出结果
如果不传递任何参数:
输出结果