【嵌入式八股18】Shell
一、Shell 种类
在 Linux 和 Unix 系统中,存在多种不同类型的 Shell,每种 Shell 都有其独特的特性和适用场景。常见的 Shell 类型如下:
| bash | 是目前最常用的 Shell,它是 Bourne Again SHell 的缩写。bash 兼容 Bourne Shell 的语法,同时增加了许多新的特性,如命令历史记录、命令补全、作业控制等,功能强大且易于使用。 |
| csh | C Shell 的缩写,其语法风格类似于 C 语言,提供了类似 C 语言的控制结构和命令历史功能,适合熟悉 C 语言的用户。 |
| ksh | Korn Shell 的缩写,结合了 Bourne Shell 的优点,并增加了一些高级功能,如数组、函数等,在性能和功能上有较好的平衡。 |
| zsh | Z Shell 的缩写,它在 bash 的基础上进行了扩展,提供了更强大的命令补全、语法高亮、主题定制等功能,受到很多开发者的喜爱。 |
二、基本语法
(一)定义和使用变量
在 Shell 脚本中,变量的定义和使用非常简单。以下是一个示例脚本:
#!/bin/sh
# 定义一个变量 a,并赋值为 "hello world"
a="hello world"
# 打印变量 a 的值
echo $a
# 注意:单引号会原样输出内容,不会进行变量替换
echo 'a is xiaxaiwen${a}'
(二)if - else 条件语句
if - else 语句用于根据条件执行不同的代码块。其基本语法如下:
if [ 条件判断 ]; then
# 条件为真时执行的代码
执行语句1
elif [ 其他条件判断 ]; then
# 其他条件为真时执行的代码
执行语句2
else
# 所有条件都不满足时执行的代码
执行语句3
fi
(三)[] 条件测试
在使用 [] 进行条件测试时,前后一定要加空格。例如:
if [ "$a" = "hello" ]; then
echo "变量 a 的值为 hello"
fi
(四)Shell 常用命令
以下是一些常见的 Shell 命令及其说明:
echo |
将文字内容打印在屏幕上,例如 echo "Hello, World!"。 |
ls |
列出文件列表,可使用不同的选项来控制输出格式,如 ls -l 显示详细信息。 |
wc |
用于计算文件的行数(-l)、单词数(-w)和字符数(-c),例如 wc -l file.txt 统计文件的行数。 |
cp |
用于文件拷贝,语法为 cp 源文件 目标文件,如 cp file1.txt file2.txt。 |
mv |
可以重命名文件或移动文件,例如 mv oldname.txt newname.txt 重命名文件,mv file.txt /new/directory/ 移动文件。 |
rm |
删除文件,使用时要谨慎,如 rm file.txt 删除指定文件。 |
grep |
在文件内搜索字符串,例如 grep 'searchstring' file.txt 在文件 file.txt 中搜索包含 searchstring 的行。 |
cut -b |
指定欲显示的文件内容范围,并将它们输出到标准输出设备。例如,输出每行第 5 个到第 9 个字符可使用 cut -b5-9 file.txt。注意不要和 cat 命令混淆,这是两个完全不同的命令。 |
cat |
输出文件内容到标准输出设备(屏幕)上,如 cat file.txt 显示文件内容。 |
file |
得到文件类型,例如 file file.txt 可查看文件的类型。 |
read var |
提示用户输入,并将输入赋值给变量,例如 read name 等待用户输入姓名并赋值给 name 变量。 |
sort |
对文件中的行进行排序,如 sort file.txt 对文件 file.txt 的行进行排序。 |
uniq |
删除文本文件中重复出现的行,通常与 sort 命令结合使用,如 `sort file.txt |
expr |
进行数学运算,例如运行 expr 2 "+" 3 得到结果为 5。注意运算符需要用引号括起来。 |
find |
搜索文件,例如根据文件名搜索可使用 find . -name filename -print,其中 . 表示当前目录。 |
tee |
将数据输出到标准输出设备(屏幕)和文件,例如 `ls |
basename |
返回不包含路径的文件名,例如 basename /bin/tux 将返回 tux。 |
dirname |
返回文件所在路径,例如 dirname /bin/tux 将返回 /bin。 |
head |
输出文本文件开头几行,默认输出前 10 行,可使用 -n 选项指定行数,如 head -n 5 file.txt 输出前 5 行。 |
tail |
输出文本文件末尾几行,默认输出后 10 行,同样可使用 -n 选项指定行数,如 tail -n 3 file.txt 输出后 3 行。 |
sed |
是一个基本的查找替换程序。可以从标准输入(比如命令管道)读入文本,并将结果输出到标准输出(屏幕)。该命令采用正则表达式进行搜索。例如,将 linuxfocus 替换为 LinuxFocus 可使用 `cat text.file |
awk |
用来从文本文件中提取字段。缺省地,字段分割符是空格,可以使用 -F 指定其他分割符。例如,`cat file.txt |
env |
显示系统预设的环境变量。 |
(五)Shell 变量类型
在 Shell 中,变量名只能包含数字、字母和下划线。以下是不同类型的 Shell 变量:
1. 局部变量
局部变量在脚本或命令中定义,仅在当前 Shell 实例中有效。例如:
#!/bin/sh
local_var="This is a local variable"
echo $local_var
2. Shell 变量特殊变量
$0 |
当前脚本的文件名。 |
$n |
传递给脚本或函数的参数。n 是一个数字,表示第几个参数。例如,第一个参数是 $1,第二个参数是 $2。 |
$# |
传递给脚本或函数的参数个数。 |
$* |
传递给脚本或函数的所有参数,将所有参数视为一个整体。 |
$@ |
传递给脚本或函数的所有参数。被双引号(" ")包含时,与 $* 稍有不同,$@ 会将每个参数单独处理。 |
$? |
上个命令的退出状态,或函数的返回值。通常,返回值为 0 表示命令执行成功,非 0 值表示执行失败。 |
$$ |
当前 Shell 进程 ID。对于 Shell 脚本,就是这些脚本所在的进程 ID。 |
(六)条件语句
1. 操作符
!! |
表示执行上一条指令。 |
!n |
表示执行命令历史中第 n 条指令。 |
* |
匹配零个或多个字符,常用于文件通配。 |
? |
匹配一个字符,常用于文件通配。 |
2. 数值比较运算符
-eq |
相等,用于比较两个数值是否相等。 |
-ne |
不等,用于比较两个数值是否不相等。 |
-gt |
大于,用于比较一个数值是否大于另一个数值。 |
-lt |
小于,用于比较一个数值是否小于另一个数值。 |
-le |
小于等于,用于比较一个数值是否小于或等于另一个数值。 |
-ge |
大于等于,用于比较一个数值是否大于或等于另一个数值。 |
3. 字符串比较运算符
= |
相等,用于比较两个字符串是否相等。 |
!= |
不等,用于比较两个字符串是否不相等。 |
-z |
空串,用于判断一个字符串是否为空。 |
-n |
非空串,用于判断一个字符串是否不为空。 |
4. 文件比较运算符
-d |
目录,用于判断一个路径是否为目录。 |
-f |
文件,用于判断一个路径是否为文件。 |
-L |
链接,用于判断一个路径是否为符号链接。 |
-r |
可读,用于判断一个文件或目录是否可读。 |
-w |
可写,用于判断一个文件或目录是否可写。 |
-x |
可执行,用于判断一个文件或目录是否可执行。 |
-s |
文件非空,用于判断一个文件是否不为空。 |
5. 逻辑运算符
-a |
逻辑与,用于连接两个条件,只有当两个条件都为真时,整个表达式才为真。 |
-o |
逻辑或,用于连接两个条件,只要有一个条件为真,整个表达式就为真。 |
! |
逻辑否,用于取反一个条件的结果。 |
6. 替换运算符
${var_name:-def_Val}:如果变量var_name存在且为非null,返回该变量的值,否则返回默认值def_Val。注意var_name与:之间没有空格,:与-之间可以有空格。主要用途是,如果变量未定义,则使用默认值。${var_name:=val}:如果变量var_name存在且为非null,返回该变量的值,否则,把val的值赋给变量var_name,并返回var_name的值val。注意var_name与:之间没有空格,:与=之间也不能有空格。${var_name:?message}:如果变量var_name存在且为非null,返回该变量的值,否则返回该变量的名字var_name及提示信息message,并退出当前命令或脚本。注意var_name与:之间没有空格,:与?之间也不能有空格。${var_name:+val}:如果变量var_name存在且为非null,返回val,否则返回null。注意var_name与:之间没有空格,:与+之间也不能有空格。${#val_name}:返回变量的长度。$(()):用于算术运算操作,例如$((5 + 1))计算结果为 6。只能使用+、-、*、/和()运算符,并且只能做整数运算。$():命令代换,类似于反引号(`),例如echo $(date)会输出当前日期和时间。
(七)循环语句用法
在 Shell 中,有多种循环语句的使用方式:
for i in $path:遍历$path变量中的每个元素。for i inseq 1 9:使用seq命令生成 1 到 9 的序列,然后遍历该序列。for i in $(seq 1 9):与上一种方式类似,使用$(...)进行命令替换。for i in {a..z}:遍历从a到z的所有字母。for (( i=1; i<=10; i++ )):类似于 C 语言的for循环,初始化i为 1,当i小于等于 10 时执行循环体,每次循环i加 1。while [ $cnt -ge 0 ]:当$cnt大于等于 0 时,执行循环体。until [ $cnt -lt 0 ]:直到$cnt小于 0 时,停止执行循环体。
(八)case 语句
case 语句用于根据不同的条件执行不同的代码块,类似于其他语言中的 switch 语句。以下是一个示例:
name=`basename $0 .sh`
case $1 in
s|start)
echo "start..."
;;
stop)
echo "stop ..."
;;
reload)
echo "reload..."
;;
*)
echo "Usage: $name [start|stop|reload]"
exit 1
;;
esac
exit 0
说明:
*)相当于其他语言中的default,当所有其他条件都不匹配时执行。- 除了
*)模式,各个分支中;;是必须的,;;相当于其他语言中的break,用于终止当前分支的执行。 |分割多个模式,相当于or,表示只要满足其中一个模式就执行相应的代码块。
(九)其他常用命令和特性
help:查看所有 bash 保留的关键词。readonly:定义变量只读,一旦定义后,变量的值不能被修改,例如readonly var="value"。unset:删除变量,例如unset var删除var变量。echo -e "Value of a is $a \n":使转义字符\n生效,可以使用的转义符有\\、\a、\b、\f、\n、\r、\t、\v。${var}:返回变量本来的值。${var:-word}:如果变量var为空或已被删除(unset),那么返回word,但不改变var的值。${var:=word}:如果变量var为空或已被删除(unset),那么返回word,并将var的值设置为word。${var:?message}:如果变量var为空或已被删除(unset),那么将消息message送到标准错误输出,可以用来检测变量var是否可以被正常赋值。若此替换出现在 Shell 脚本中,那么脚本将停止运行。${var:+word}:如果变量var被定义,那么返回word,但不改变var的值。val=`expr 2 + 2`:进行算数运算,将结果赋值给val变量。echo ${#string}:获取字符串的长度。echo ${string:1:4}:输出第 1 位到第 4 位的字符串(从 0 开始)。
三、数组
(一)定义数组
在 Shell 中,可以使用多种方式定义数组:
# 方式一:直接赋值
array_name=(value0 value1 value2 value3)
# 方式二:分行赋值
array_name=(
value0
value1
value2
value3
)
# 方式三:逐个赋值
array_name[0]=value0
array_name[1]=value1
array_name[2]=value2
(二)数组访问
以下是一些常见的数组访问方式:
# 获取数组中指定索引的值
echo ${array_name[2]}
# 获取数组的所有元素
echo ${array_name[*]}
echo ${array_name[@]}
# 获取数组的元素个数
echo ${#array_name[@]}
echo ${#array_name[*]}
# 获取数组单个元素的长度
echo ${#array_name[2]}
四、重定向
重定向用于改变命令的输入输出方向,以下是一些常见的重定向示例:
# 将标准错误输出(stderr)重定向到文件
$ command 2 > file
# 将标准输入(stdin)重定向到文件
$ command < file
# 将标准输出(stdout)重定向到文件
$ command > file
# 将标准输出和标准错误输出都重定向到文件
$ command > file 2>&1
# 将标准输入重定向到 file1,标准输出重定向到 file2
$ command < file1 > file2
其他相关选项和命令
-cp:表示cp命令报错了不会停止,继续执行下面的操作。@cp:终端中不会打印出命令的执行信息。declare:-i:声明整型变量,例如declare -i num=10。-a:声明数组,例如declare -a my_array。-f:列出所有定义过的函数。-x:将声明的变量作为脚本的环境变量导出,例如declare -x var="value"。
shift:左移参数,shift 3表示$4变成$1,不带参数的话默认为shift 1。
五、字符串操作
在 Shell 中,可以对字符串进行各种操作,以下是一些示例:
file=/dir1/dir2/dir3/my.file.txt
# 删掉第一个 / 及其左边的字符串
echo ${file#*/} # 输出:dir1/dir2/dir3/my.file.txt
# 删掉最后一个 / 及其左边的字符串
echo ${file##*/} # 输出:my.file.txt
# 删掉第一个 . 及其左边的字符串
echo ${file#*.} # 输出:file.txt
# 删掉最后一个 . 及其左边的字符串
echo ${file##*.} # 输出:txt
# 删掉最后一个 / 及其右边的字符串
echo ${file%/*} # 输出:/dir1/dir2/dir3
# 删掉第一个 / 及其右边的字符串
echo ${file%%/*} # 输出:(空值)
# 删掉最后一个 . 及其右边的字符串
echo ${file%.*} # 输出:/dir1/dir2/dir3/my.file
# 删掉第一个 . 及其右边的字符串
echo ${file%%.*} # 输出:/dir1/dir2/dir3/my
# 提取最左边的 5 个字节
echo ${file:0:5} # 输出:/dir1
# 提取第 5 个字节右边的连续 5 个字节
echo ${file:5:5} # 输出:/dir2
# 将第一个 dir 替换为 path
echo ${file/dir/path} # 输出:/path1/dir2/dir3/my.file.txt
# 将全部 dir 替换为 path
echo ${file//dir/path} # 输出:/path1/path2/path3/my.file.txt
# 计算字符串长度
echo ${#file} # 输出:27
记忆方法:
#是去掉左边(键盘上#在$的左边)。%是去掉右边(键盘上%在$的右边)。- 单一符号是最小匹配;两个符号是最大匹配。
六、命令中出现的双横杆 --
双横杆 -- 是为了告诉命令,后面的内容不是命令参数,标识命令参数结束(marks the end of options)。例如,要生成一个名为 -f 的文件:
# 直接使用该命令会报错,因为 -f 被当作选项处理
$ touch -f
usage:
touch [-A [-][[hh]mm]SS] [-acfhm] [-r file] [-t [[CC]YY]MMDDhhmm[.SS]] file ...
# 加双横杆,告诉 touch 命令后面的 -f 是文件名
$ touch -- -f
# 查看生成的文件
$ ll
-rw-r--r-- 1 xxw staff 0B 9 29 17:43 -f
#牛客激励计划#嵌入式八股/模拟面试拷打 文章被收录于专栏
一些八股模拟拷打Point,万一有点用呢
