目录
前言
shell是一个人机交互接口,可以将用户输入的命令发送给系统运行并反馈运行结果。
1. 界面
shell属于系统软件,通常称为“终端”。界面如下:
一般用户shell以"$"符号为命令提示符,当用户切换为root时,提示符变成“#”。
2. 常用快捷键
Ctrl+n相当于下箭头(next line)
Ctrl+p相当于上箭头(previous line)
Ctrl+r 检索使用过的历史命令(retrieve)
Ctrl+a:相当于Home键,光标移到行首(ahead)
Ctrl+e:相当于End键,光标移到行尾(end)
Ctrl+b:光标向左移动一个字符(backwards)
Ctrl+ f:光标向右移动一个字符(forwards)
Alt+b:光标向左移动一个单词
Alt+f:光标向右移动一个单词
Ctrl+w: 剪切光标前一个单词
Ctrl+k:剪切光标处到行尾的字符
Ctrl+u:剪切光标处到行首的字符
Ctrl+y:粘贴前面剪切的文本
Ctrl+h:相当于Backspace键,向左删除一个字符
Ctrl+d:相当于Delete键,向右删除一个字符
Ctrl+t: 交换光标所在字符和前一个字符
Alt+t:交换光标前两个单词
Alt+l:将光标后一个单词小写
Alt+u:将光标后一个单词大写
Alt+c:将光标后一个单词首字母大写(单词中其他大写字母会自动更改为小写)
Ctrl+s:使当前快速输出的屏幕静止
Ctrl+q:退出Ctrl+s屏幕静止
Ctrl+z:使正在运行在终端的任务,运行于后台
Ctrl+c:终止终端中正在执行的任务
Ctrl+d: 结束当前命令
Ctrl+l: 类似于执行命令"clear",但是不清空历史显示内容
Esc键:连续按3次显示所有的支持的终端命令
Tab键:命令、变量、文件名等自动补全
3. 历史命令列表
执行以下命令可以列出最近500个历史命令,每个命令前都标有序号,使用!+序号可以直接运行对应命令,使用fc+序号,可以打开一个文件,编辑对应命令行,使用fc -e可以指定编辑器 。
history 列出近500个历史命令,结果如下:
……
241 cat -n 2 cmd
242 cat -n cmd
243 clear
244 exit
245 exit
246 history
……
!244 运行序号为244的历史命令
fc -e nano 指定编辑器为nano
fc 244 打开文本编辑器,编辑序号为244的历史命令,保存退出后立即执行
$HISTSIZE = 10 可以将历史命令存储数量调整为10个
echo $HISTFILE 可以查看历史命令存储文件名称及位置
3. 通配符和特殊字符
* 任意数量的任意字符
? 单个任意字符
[] 精确匹配括号中的字符,可以用“-”表示序列,比如test.[a-c]表示test.a、test.b、test.c,以"!"或者"^"符号表示否运算,比如test.[!a]表示不以a结尾的文件
{} 列举方式,可以用".."表示序列,比如test.{a..c}表示test.a、test.b、test.c
root@L-debian:/home/test# ls
cmd
root@L-debian:/home/test# mkdir {tree,list,{tree,list}/test.{1..3},tree/test.{x..z}}
root@L-debian:/home/test# tree
.
├── cmd
├── list
│ ├── test.1
│ ├── test.2
│ └── test.3
└── tree
├── test.1
├── test.2
├── test.3
├── test.x
├── test.y
└── test.z
11 directories, 1 file
root@L-debian:/home/test# cd tree
root@L-debian:/home/test/tree# ls test.[x-z]
test.x:
test.y:
test.z:
root@L-debian:/home/test/tree# ls test.[!x-z]
test.1:
test.2:
test.3:
\ 转义字符,引用其后面的专用字符,后面输入Enter键时,意为将一行命令分成多行执行
; 在一行内执行多个命令时,使用";"分隔
&& 连接过个命令,只有前一个命令为真(执行成功)时,才执行下一个命令
root@L-debian:/home/test# ls
cmd list tree
root@L-debian:/home/test# mkdir test.xy\? #将通配符?作为文件名的一部分
root@L-debian:/home/test# ls
cmd list 'test.xy?' tree
root@L-debian:/home/test# mkdir test\
> .cc #这里的.cc将连接到上一行,作为文件名的一部分处理
root@L-debian:/home/test# ls
cmd list test.cc 'test.xy?' tree
root@L-debian:/home/test# mkdir test.cc ; ls #先后执行两个命令
cmd list test.cc 'test.xy?' tree
root@L-debian:/home/test# rm test.cc && ls
rm: 无法删除 'test.cc': 是一个目录 #因为第一个命令未能成功执行,第二个命令将不执行
4. 输入输出与重定向
输入输出分三类:标准输入(0)、标准输出(1)、错误输出(2)。
一般情况下,标准输入为键盘输入,标准输出为屏幕输出,如果需要更改输入输出方式,就涉及到重定向的问题。
< 将标准输入重定向到其后文件或设备
root@L-debian:/home/test# sort #按照首字母排序,后面没有接参数,代表参数为标准输入
8
20
12
20 #从键盘输入8回车,20回车,12回车,20回车,然后使用Ctrl+d结束输入,以下为运算结果
12
20
20
8
root@L-debian:/home/test#
root@L-debian:/home/test# cat in #in文件中包含4个字符串
hello
good
word
sorry
root@L-debian:/home/test# sort < in #将sort的输入重定向为in文件,运行结果如下
good
hello
sorry
word
root@L-debian:/home/test#
> 将标准输出重定向到其后文件或设备,如文件已存在则覆盖原文件,如果文件不存在则新建该文件
>> 将标准输出追加到其后文件或设备的结尾
root@L-debian:/home/test# ls -C > dir #将ls输出结果重定向到dir文件
root@L-debian:/home/test# cat dir
cmd dir err in list test.cc test.xy? tree
root@L-debian:/home/test# ls -C >> dir #将ls输出结果追加到dir文件
root@L-debian:/home/test# cat dir
cmd dir err in list test.cc test.xy? tree
cmd dir err in list test.cc test.xy? tree
2> 将标准错误重定向到其后文件或设备
2>> 将标准错误追加到其后文件或设备的结尾
root@L-debian:/home/test# rmdir list 2> err #重定向之后,屏幕不再输出错误信息
root@L-debian:/home/test# cat err
rmdir: 删除 'list' 失败: 目录非空
2>&1 将标准错误重定向到标准输出
>& 将标准输出和标准错误都重定向到其后文件或设备
|& 将标准错误重定向为其后命令的输入(参数)
| 管道符,将前一个命令的运行结果传递给后一个命令作为输入(参数)
#第一个命令的错误输出,作为第二个命令的参数
root@L-debian:/home/test# rmdir list |& cat -n
1 rmdir: 删除 'list' 失败: 目录非空
#第一个命令的运行结果,作为第二个命令的参数
root@L-debian:/home/test# ls -laF | cat -n
1 总用量 28
2 drwxr-xr-x 6 root root 4096 10月 6 12:08 ./
3 drwxr-xr-x 4 root root 4096 10月 6 11:25 ../
4 -rwxr--r-- 1 root root 14 10月 5 17:20 cmd*
5 drwxr-xr-x 5 root root 4096 10月 6 11:26 list/
6 drwxr-xr-x 2 root root 4096 10月 6 12:08 test.cc/
7 drwxr-xr-x 2 root root 4096 10月 6 12:07 test.xy?/
8 drwxr-xr-x 8 root root 4096 10月 6 12:06 tree/
5. 后台作业管理
& 在命令后加上此字符,命令将会在后台运行,并提供一个作业号
bg 命令运行过程中,使用Ctrl+z暂停,使用该命令将正在进行的作业转到后台
jods 列出正在后台运行的命令及作业号
ps -a 列出所有正在执行的所有前台和后台命令
notify 后接作业号,要求指结尾而定的命令完成后发送通知
fg 后接作业号,将指定的后台作业带到前台
kill 后接作业号,结束指定的后台作业
如果想要在指定时间运行命令,可以使用at命令,功能非常强大。
#将标准输出及错误输出送入null,并在后台运行,得到作业号为1
root@L-debian:/home/test# apt update >& /dev/null &
[1] 12473
#列出后台作业号为1的相关信息
root@L-debian:/home/test# jobs
[1]+ 已完成 apt update &> /dev/null
#结束作业号为1的后台作业
root@L-debian:/home/test# kill 1
6. 变量
#定义变量VAR,后接等号,不能加空格
root@L-debian:/home/test# VAR='What is your name?'
#引用变量时使用$符号
root@L-debian:/home/test# echo $VAR
What is your name?
可以使用反引号(位于Esc下方的~和`键),将一个命令执行的结果赋给变量
#先看一下ls的运行结果
root@L-debian:/home/test# ls
cmd dir err in list test.cc 'test.xy?' tree
#使用反引号将ls的运行结果赋给VAR
root@L-debian:/home/test# VAR=`ls`
#调用VAR的结果
root@L-debian:/home/test# echo $VAR
cmd dir err in list test.cc test.xy? tree
7. 脚本
如果将一系列shell命令保存在一个文本文件中,给这个文件赋予运行权限,就形成一个脚本。
脚本可以使用参数运行,其命令行的变量以"$"开头,按照顺序从1开始编号,比如$1,$2,$3。运行脚本时,也要按照对应顺序为变量赋值。
#新建脚本文件run
root@L-debian:/home/test# touch run
#编辑脚本文件,写入5条命令,两个变量引用
root@L-debian:/home/test# nano run
root@L-debian:/home/test/tree# cat run
echo ---------------
tree $1
echo ---------------
ls -R $2
echo ---------------
#向脚本文件赋予运行权限
root@L-debian:/home/test# chmod u+x run
#运行脚本文件,向$1变量传递参数tree,向$2变量传递参数tree
root@L-debian:/home/test/tree# ./run tree tree
---------------
tree
├── test.1
└── test.x
2 directories, 0 files
---------------
tree:
test.1 test.x
tree/test.1:
tree/test.x:
---------------
8. 控制结构
8.1 判定
控制结构必须对运行结果进行判断,才能达到控制的目的。
test命令可以判定命令执行结果,如下:
test A 判定选项 B
也可以使用 [ ] 进行判定,如下:
[ $var = 10 ]
无论是test命令还是 [ ] 的方式,都可以使用以下判定选项:
数值的判定选项如下:
-gt 大于
-lt 小于
-ge 大于等于
-le 小于等于
-eq 等于
-ne 不等于
字符串的判定选项如下:
-z 空字符串测试
= 字符串相等
!= 字符串不相等
逻辑运算的判定选项如下:
-a 逻辑与
-o 逻辑或
! 逻辑非
文件操作的选项如下:
-f 存在的文件,而且是一个规则文件
-s 非空文件
-r 可读文件
-w 可写和修改的文件可执行文件
-x 可执行文件
-d 文件名是目录名
#run.s内容如下:
ron@L-debian:~/test$ cat run.s
read num
test $num -eq 10
echo $?
ron@L-debian:~/test$ ./run.s
10 #输入10,回车
0 #判定结果为真,返回0
ron@L-debian:~/test$ ./run.s
20 #输入20,回车
1 #判定结果为假,返回0以外的数值
#使用[]判定示例如下:
ron@L-debian:~/test$ cat run.s1
read num
[ $num = 10 ]
echo $?
ron@L-debian:~/test$ ./run.s1
10
0
8.2 循环控制结构
循环控制结构的语句主要有下:
while 判定 do 命令 done 如果判定为真,执行循环
until 判定 do 命令 done 如果判定为假,执行循环
for 值 in 列表 do 命令 done 如果值在列表中,继续循环
#while用法示例
ron@L-debian:~/test$ cat loo.s
read i
while [ $i -lt 3 ]
do
echo $i
((i++))
done
ron@L-debian:~/test$ ./loo.s
1
1
2
#until用法示例
ron@L-debian:~/test$ cat loo.s1
read i
until [ $i -lt 3 ]
do
echo $i
((i--)) # (())内可以直接使用C语言命令格式
done
ron@L-debian:~/test$ ./loo.s1
5
5
4
3
#for用法示例
ron@L-debian:~/test$ cat loo.s2
read i
for i in {1..3}
do
echo $i
done
ron@L-debian:~/test$ ./loo.s2
1
1
2
3
8.3 条件控制结构
条件控制结构的语句主要有下:
if 判定; then
命令;
fi;
#判定为真,执行命令,判定为假直接退出
特别要注意:每一条命令的结尾一定要用;来声明本条命令结束
if 判定1; then
命令1;
else
命令2;
fi;
#判定1为真则执行命令1,判定1为假则执行命令2
if 判定1; then
命令1;
elif 判定2; then
命令2;
else
命令3;
fi;
#判定1为真则执行命令1,判定1为假则执行判定2,若判定2为真则执行命令2,若判定2也为假则直接退出
ron@L-debian:~/test$ cat if.s1
read i;
if [[ $i -gt 10 ]]; then
echo $i is standard;
elif [[ $i -gt 0 ]]; then
echo $i is less;
else
echo $i is err;
fi;
#运行结果如下
ron@L-debian:~/test$ ./if.s1
11
11 is standard
ron@L-debian:~/test$ ./if.s1
10
10 is less
ron@L-debian:~/test$ ./if.s1
0
0 is err
case 变量 in
预设值1)
命令1;
;;
预设值2)
命令2
;;
……
esac
#逐项判定变量与预设值1、预设值2……是否一致,判定为真则执行对应命令。
ron@L-debian:~/test$ cat case.s
read i;
case $i in
11 | 12 | 13)
echo $i 正常;
;;
8 | 9 | 10)
echo $i 偏小;
;;
*)
echo $i 错误;
;;
esac;
#运行结果如下
ron@L-debian:~/test$ ./case.s
12
12 正常
ron@L-debian:~/test$ ./case.s
8
8 偏小
ron@L-debian:~/test$ ./case.s
-4
-4 错误
9. 过滤器
grep可以用来搜索并显示搜索结果,也可以对其他输出结果进行过滤。其中涉及到一下规则表达式:
^ 一行的开始
$ 一行的结束
. 任何一个可能的字符
* 任何一个重复的字符
[] 字符集
示例如下:
#在以if.开头的所有文件里搜索if
ron@L-debian:~/test$ grep if if.*
if.s:if [[ $i -gt 10 ]]; then
if.s1:if [[ $i -gt 10 ]]; then
if.s1:elif [[ $i -gt 0 ]]; then
#现有文件夹内容如下
ron@L-debian:~/test$ ls -laF
总用量 32
drwxr-xr-x 5 ron ron 4096 10月 11 12:09 ./
drwxr-xr-x 21 ron ron 4096 10月 10 18:06 ../
-rwxr--r-- 1 ron ron 126 10月 11 11:26 case.s*
drwxr-xr-x 2 ron ron 4096 10月 11 12:08 dir1/
drwxr-xr-x 2 ron ron 4096 10月 11 12:09 dir2/
drwxr-xr-x 2 ron ron 4096 10月 11 12:08 dir3/
-rwxr--r-- 1 ron ron 80 10月 11 10:45 if.s*
-rwxr--r-- 1 ron ron 126 10月 11 10:59 if.s1*
#仅显示文件(文件以*结尾)
ron@L-debian:~/test$ ls -laF | grep $'*'
-rwxr--r-- 1 ron ron 126 10月 11 11:26 case.s*
-rwxr--r-- 1 ron ron 80 10月 11 10:45 if.s*
-rwxr--r-- 1 ron ron 126 10月 11 10:59 if.s1*
#仅显示文件夹(文件夹以d开头)
ron@L-debian:~/test$ ls -laF | grep ^d
drwxr-xr-x 5 ron ron 4096 10月 11 12:09 ./
drwxr-xr-x 21 ron ron 4096 10月 10 18:06 ../
drwxr-xr-x 2 ron ron 4096 10月 11 12:08 dir1/
drwxr-xr-x 2 ron ron 4096 10月 11 12:09 dir2/
drwxr-xr-x 2 ron ron 4096 10月 11 12:08 dir3/
#仅显示文件夹(文件夹以/结尾)
ron@L-debian:~/test$ ls -laF | grep $'/'
drwxr-xr-x 5 ron ron 4096 10月 11 12:09 ./
drwxr-xr-x 21 ron ron 4096 10月 10 18:06 ../
drwxr-xr-x 2 ron ron 4096 10月 11 12:08 dir1/
drwxr-xr-x 2 ron ron 4096 10月 11 12:09 dir2/
drwxr-xr-x 2 ron ron 4096 10月 11 12:08 dir3/
总结
这里所整理的,仅仅是shell的皮毛。