1,什么是bash shell
在linux内核下,无论什么版本的linux发行版,都会有下列的shell支持。BASH,CSH,TCSH,ZSH,SCSH. 这些shell都是由最初的shell发展而来的。你可以参考如下的框架图理解。
通过上面的关系图,可以清楚的明白,shell是用户需求和linux内核之间的一个转换媒介,用户为了让linux系统处理用户的需求完成特定的任务,用户可以编写shell,运行shell程序就能实现与linux内核之间的交互,linux内核与计算机的底层硬件之间存在双向的交互,从而实现控制硬件的功能。shell语言是一种命令行语言的交互。
2,CLI(commond line interface),命令行交互
shell语言提供与linux内核之间的交互,这样我们就可以通过命令行键入命令就可以实现与linux的交互。
2.1 怎么找到当前的shell 类型
$ cat /etc/shells
>>
# /etc/shells: valid login shells
/bin/sh
/bin/bash
/bin/rbash
/bin/dash
/usr/bin/tmux
因为我使用的是ubuntu系统而且安装了tmux工具,所以会有/usr/bin/tmux。你可能会没有,这里,每个人的情况可能都不相同。当时学习的是bash,支持bash即可。
2.2 基础的命令行快捷键
快捷键 | 含义 |
---|---|
CTRL-L | 清除命令窗口 |
CTRL-W | 删除当前命令行中光标所在位置的一个单词 |
CTRL-U | 删除当前命令行一行的全部内容 |
CTRL-R | 搜索之前使用过的命令 |
CTRL-C | 取消当前正在运行的命令 |
例如,你可以在命令行输入date命令。
$ date
>>
2018年 11月 26日 星期一 09:16:14 CST
这是当你输入快捷键 CTRL+L则命令窗口会被清空!,你可一不断尝试理解上面表格的命令含义。
2.3 ,在linux中获得命令的帮助
如果你使用过python,matlab你会很清除的理解help是什么。当你不知道**某一和函数或者关键词**的意义或者怎么使用时,你可以使用help等指令,在linux中你可以在命令行中使用如下三种方式查看某一个指令的含义和使用方式
man date
info date
date --help
3, shell 编程的大体流程总结
3.1 type 命令
type命令是用来找出一个命令,它是属于内嵌(build-in)还是外部的二进制可执行文件
例如,
$ type -a ls
>>
ls is aliased to `ls --color=auto'
ls is /bin/ls
$ type -a date
>>
date is hashed (/bin/date)
$ type -a history
>>
history is a shell builtin
$ type -a echo
>>
echo is a shell builtin
echo is /bin/echo
等等命令,都可以使用type命令查看它的类型。这里
# -a,a是值all的意思
$ type -a
3.2 起手“Hello,world!”
- 打开一个命令行,通过ctrl+alt+t.
- 进入你学习bash自己建立的文件夹内,创建一个bash文件,比如 vim begin00.sh 当然后缀名.sh不一定是必要的,当时为了区分不造成误解,我就加上了。
- 在文件第一行输入#! /bin/bash
因为我比较习惯使用vim编辑器,所以我都会一直使用vim创建或者打开一个文件,当然你可以使用gedit等其他编译器做同样的操作。
如果你像学习vim可以参考这两篇文章,
言归正传,你的文件应该是这样的 ```bash #! /bin/bash echo "Hello, world!" ``` ***关于第一句#!/bin/bash,#是注释,!是特殊字符告诉编译器去下面的位置对应的编译器对该文件一下全部内容作解释。你可以通过type命令查看bash的位置*** ```bash $ type -a bash >> bash is /bin/bash ``` 第二句使用了echo命令,就是输出双引号中的全部内容。
3.3 bash文件设置成可执行文件,执行bash程序
$ chmod +x "你的文件存放的路径"/"文件名"
#for instance
$ chmod +x ~/Public/bash_lerning/begin00.sh
然后打开一个命令窗口,执行程序,有下面三种方法:
$ . "文件路径"/"文件名"
$ ./"文件路径"/"文件名"
$ bash /"文件路径"/"文件名"
例如,
$ . ~/Public/base_learning/begin00.sh
>>
Hello, world!
如果不设置可执行文件即不执行3.3操作,则直接运行bash文件会提示:bash: “文件”: Permission denied!
3.4 debug bash script
有5种方式,对bash 脚本进行debug
$ bash -x bash-name #第一种
$ bash -xv bash-name #第二种
第3种方式,在bash文件中设置
#! /bin/bash -x
第4种方式,在bash文件中设置
#! /bin/bash
## Turn on debug mode##
set -x
...
...
...
##Turn off debug mode##
set +x
第5种
#!/bin/bash -x
set -n #只阅读bash程序,不执行程序
set -o noexec
第5种方式一般用来检查bash文件的是否存在语法错误
4, shell中的变量
4.1 系统变量
可以通过如下3种指令查看系统变量
$ set
$ env
$ printenv
4.2 bash shell的变量
4.2.1 bash shell的变量语法是:
varName=someValue
注意等号两边都不能加空格,这和python,matlab等语言的语法规则很不相同
举个栗子:
#! /bin/bash
var1="hello, world"
var2 = 123
echo "var1= ${var1}"
echo "var2= ${var2}"
在命令行中执行如下操作
chmod +x begin00.sh
./begin00.sh
>>
./begin00.sh: line 3: var2: command not found
var1= hello, world!
var1=
bash编译器解释时,会认为等号左边带空格的var2是一个cmd命令,因此报错,但是var1是完全正确的。这也就是bash变量的使用方法。
${varName}----推荐
$varName ------不推荐,容易产生误解。
4.2.2 怎么显示(打印)变量的值
两种方法,一种是echo,一种是C++语言的风格的printf。
语法
echo "${varName}"
print "${varName}" #printf中的使用方法和C++中的一致
继续一上面的例子说明,
#! /bin/bash
var1="hello, world!"
var2=123
echo "var1= ${var1}"
printf "var2= %d\n" ${var2}
执行程序:
$ ./begin00.sh
>>
var1= hello, world!
var2= 123
4.2.3 bash shell 中变量的默认值
语法
echo ${varName=somevalue1 somevalue1} #第1种
或者
echo ${varName:=somevalue1 somevalue1} #第2种
或者
echo ${varName-somevalue1 somevalue1} #第3种
虽然这三种都可以赋予默认值,当时1,2两种是区别于第3种的,举个栗子:
echo ${var3:=34 56}
echo ${var4-23 45 78}
echo ${var5=-23 -45}
echo ${var3}
echo ${var4}
echo ${var5}
执行结果,如下:
./begin00.sh
34 56
23 45 78
-23 -45
34 56
-23 -45
对应代码可知,使用第3种方式给变量的默认值,在使用一次后,会立即释放,相当于执行了unset指令,而第1,2两种方法会一直保存在变量中。
4.3 自行代码分析
下面贴出一部分代码和运行结果,供学习分析,比较简单的入门:
#! /bin/bash
#================================================================
# Copyright (C) 2018 * Ltd. All rights reserved.
#
# File name : begin01.sh
# Author : simileciWH
# Email : simileci.wh.32@outlook.com
# Created date: 2018-11-14 10:44:55
# Description : code is far away from bugs with the god animal protecting
#
#================================================================
echo hello world
echo "hello world"
echo "Current data: $(date) @ $(hostname)"
echo "Network configuration"
/sbin/ifconfig
pwd
/bin/pwd
echo "Hello, ${LOGNAME}"
echo "Today is $(date)"
echo "Users currently on the machine, and their processes:"
w #use man w to help yourself
执行结果:
hello world
hello world
Current data: 2018年 11月 26日 星期一 11:27:52 CST @ pcMaster
Network configuration
enp7s0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500
ether 28:d2:44:35:bc:85 txqueuelen 1000 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
device interrupt 19
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
loop txqueuelen 1000 (Local Loopback)
RX packets 2786 bytes 424414 (424.4 KB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 2786 bytes 424414 (424.4 KB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
wlp8s0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.31.129 netmask 255.255.255.0 broadcast 192.168.31.255
inet6 fe80::c363:6e0f:c564:4f4f prefixlen 64 scopeid 0x20<link>
ether a4:db:30:bf:8d:c1 txqueuelen 1000 (Ethernet)
RX packets 295059 bytes 332704942 (332.7 MB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 132331 bytes 16925943 (16.9 MB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
/home/simileciwh/Public/bash_begin
/home/simileciwh/Public/bash_begin
Hello, simileciwh
Today is 2018年 11月 26日 星期一 11:27:52 CST
Users currently on the machine, and their processes:
11:27:52 up 3:18, 1 user, load average: 0.87, 0.69, 0.63
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
simileci :0 :0 08:10 ?xdm? 5:11 0.00s /usr/lib/gdm3/g
5,引用quoting
bash script中有3中quote(引用)符号:
quote type | 名称 | 含义 |
---|---|---|
" | 双引号 | 保护双引号中的所有内容,除了,$ , ’ , " 和 \ 这4中特殊符号。变量和命令行是可以被替换的。 |
’ | 单引号 | 保护单引号中的所有内容,不准替任何换。 |
\ | 反斜杠 | 取消特殊字符的功能或意义。 |
举个栗子:
使用系统变量HOSTNAME,为例,HOSTNAME的值为你的电脑的名字,每个人不相同。
#! /bin/bash
echo "${HOSTNAME}" #系统变量会被替换
echo '${HOSTNAME}' #系统变量不会被替换
echo "\${HOSTNAME}" #特殊字符$的功能被取消!
执行结果:
pcMaster
${HOSTNAME}
${HOSTNAME}
6,获得用户从键盘的输入
6.1 read -p
read 指令:
"语法":
read -p "prompt" variable1 variable2 variableN
参数"-p",是给用户显示提示信息,
变量variable1,variable2,…,variableN是可选则的存储用户输入参数的的变量,其个数是可以选择的。
举个栗子:
#! /bin/bash
read -p "请输入你的姓名:" name
echo "Hi, ${name}. I have remember you!"
不要忘记,将文件设置成可执行文件!
运行结果:
请输入你的姓名:simileciwh
Hi, simileciwh. I have remember you!
6.2 read -t
有时候,我们需要限制与用户输入的时间,或者不是一直处于等待用户输入的状态,因此需要设置timeout input的机制,让等待输入的窗口在一段时间后就自动关闭。
"语法":
read -t Num -p "prompt" var1 var2 varN
参数-t是timeout的意思,Num时间单位为秒(s),即等到Num秒后,自动结束不在等待用户输入。
6.3 read -s
当在获取用户密码时,不希望用户输入的密码是显示出来的,因此可以使用参数-s使得用户的输入隐藏起来不显示出来。
"语法":
read -s -p "prompt" variable
6.4 read -r批处理多个变量的赋值
举个栗子:
nameservers="12 23 546"
echo "$nameservers"
read -r v1 v2 v3 <<< "$nameservers"
echo "v1=$v1, v2=$v2, v3=$v3"
运行结果:
12 23 546
v1=12, v2=23, v3=546
7,算数运算
运算符 | 描述 | 例子 |
---|---|---|
+ | 加法 | echo $((2+3)) |
- | 减法 | echo $((5-2)) |
* | 乘法 | echo $((2*3)) |
/ | 除法 | echo $((4/2)) |
% | 取余 | echo $((5%2)) |
++ | 自加 | x=2; echo $((x++)),x=2; echo $((++x)) |
-- | 自减 | x=3; echo $((x–)),x=3; echo $((–x)) |
** | 乘方 | echo $((10**2)) |
这些和C语言中的规则都不冲突
8,declare
使用declear命令设置变量的值和属性。
"语法":
declare [参数] variable
参数可选如下:
参数 | 含义 |
---|---|
-i | 变量类型----整型 |
-r | 变量类型----readonly----只读 |
-x | 设置类型为export |
-g | 创建一个在函数中使用的全局变量;否则忽略 |
-p | 显示变量的属性和值 |
还有一些其他的属性,可以通过help命令查看。
9,创建常数变量
有两种方法,一种是使用readonly命令,另一种是使用declare -r命令。常数变量的值一但被初始化,那么即使使用unset不可修改。
举个栗子:
readonly var1=23
declare -r var2=32
var1=34
var2=45
echo "var1= ${var1}"
echo "var2= ${var2}"
unset var1
var1=34
echo "var1= ${var1}"
运行结果:
./123.sh: line 3: var1: readonly variable
./123.sh: line 4: var2: readonly variable
var1= 23
var2= 32
./123.sh: line 7: unset: var1: cannot unset: readonly variable
./123.sh: line 8: var1: readonly variable
var1= 23