Linux学习(13)--初识bash shell
来源:互联网 发布:必应for mac 编辑:程序博客网 时间:2024/06/05 02:40
bash shell
我们知道,操作系统其实就是一组软件,由于这组软件在控制整个硬件与管理系统的活动监测,如果这组软件被用户随意操作,若用户操作不当,将会使得整个系统崩溃。
但是系统总还是需要用户操作系统的,所有就有了在操作系统上面发展的应用程序。用户可以通过应用程序来指挥内核,达到我们的目的。其实 shell 的功能只是提供用户操作系统的一个接口,因此这个 shell 需要可以调用其它软件才好。
Tips:也就是说,只要能操作应用程序的借口能够被称之为 shell。狭义的 shell 指的是命令行方面的软件,包括本章要介绍的 bash 等。广义的 shell 则包括图形界面的软件,因为图形界面也能够操作各种应用程序。
bash 的内置命令:type
通过 type 命令,我们可以知道这个命令是外部命令(非 bash 所提供的命令)或是内置在 bash 当中的。比如:
[root@mars ~]# type [-tpa] name选项与参数:type:不加任何参数,会显示 name 是外部命令还是内部-t:当加入 -t 参数时,type 会将 name 以下面这些字显示出它的意义: file:表示为外部命令 alias:表示该命令为命令别名所设置的名称 builtin:表示该命令为内置命令-p:如果后面接的 name 为外部命令时,才会显示完整的文件名-a:会由 PATH 设置的路径中,将所有含 name 的命令都列出来,包含alias范例1:查询 ls 是否为内置[root@mars ~]# type lsls is aliased to `ls --color=auto' <==列出ls最主要的使用情况[root@mars ~]# type -t lsalias <==仅列出ls执行时的依据[root@mars ~]# type -a lsls is aliased to `ls --color=auto' <==最先使用 aliase ls is /usr/bin/ls <==还有找到外部命令在/bin/ls范例2:那么 cd 呢?[root@mars ~]# type cd cd is a shell builtin
shell 的变量
变量就是以一组文字或符号等,来替代一些设置或者是一串保留的数据。比如我们常说的 $PATH 变量,我们之所在任何目录下都可以执行 ls 命令,都是因为 ls 这个执行文件所在的目录/usr/bin 在PATH里面,可以被随时检测到。
我们使用echo就可以看到变量:
[root@mars ~]# echo $PATH/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
变量的设置规则
1.变量与变量内容以一个等号“=”来连接
2.等号两边不能直接接空格符,如下所示为错误的
myname = VBird 或 myname=VBird Tsai
3.变量名称只能是英文字母与数字,但是开头字符不能是数字,以下为错误:
2myname=VBird
4.变量内容若有空格符可使用双引号或者单引号将变量内容结合起来,但
- 双引号内的特殊字符如 $ 等,可以保留原本的特性,如下所示:
var = “lang is $LANG” 则 echo \$var 可得 lang is en_US
- 单引号内的特殊字符则为一般字符(纯文本),如下:
var=’lang si $LANG’ 则 echo \$var 可得 lang is \$LAGN
5.可用转义字符“\”将特殊符号(如Enter、$、\、空格等)变成一般字符
6.在一串命令中,还需要通过其他的命令提供的信息,可以使用反单引号“ `命令` ”或“ $(命令)”。注意,是键盘数字1 键旁边的那个键,不是单引号。例如湖区内核版本的设置:
version=$(uname -r)
再echo $version
可得“2.6.18-128.el5”7.若该变量为了增加变量内容时,则可用“$ 变量名称”或 \${变量} 累加内容,如下所示:
PATH=”$PATH”:/home/bin
8.若该变量需要在其他子进程执行,则需要以 export 来使变量变成环境变量
export PATH
9.通常大写字符为系统默认变量,自行设置变量可以使用小写字符,方便判断
10.取消变量的方法为使用“unset 变量名称”
具体设置内容以及注意项,如下所示:
范例1:设置一个变量 name,且内容为 VBird's name[root@mars ~]# name=VBird's name# 单引号与双引号必须要成对,在上面的设置中仅有一个单引号,因此当你按下# Enter后,你还可以继续输入变量内容。这与我们需要的功能不同,按Ctrl+C结束[root@mars ~]# name="VBird's name" <==正确[root@mars ~]# name='VBird's name' <==单引号不成对,失败[root@mars ~]# name=VBird\'s\ name <==转义字符也行范例2:在PATH变量中累加 /home/dmtsai/bin 这个目录[root@mars ~]# PATH=$PATH:/home/dmtsai/bin[root@mars ~]# PATH="$PATH":/home/dmtsai/bin[root@mars ~]# PATH=${PATH}:/home/dmtsai/bin# 三种方式都可以范例3:如果要将 name 的内容多出“yes”呢[root@mars ~]# name=$nameyes# echo 发现为空白,如果没有双引号,那么变量就变成了$nameyes这个的内容# 但是我们没有设置 nameyes 这个变量,自然为空[root@mars ~]# name="$name"yes[root@mars ~]# name=${name}yes <==两种方式都可以范例4:如何让刚刚的 name 可以用在下个 shell 的程序[root@mars ~]# bash <==进入子进程[root@mars ~]# echo $name <==什么都没有[root@mars ~]# exit <==离开子进程[root@mars ~]# export name [root@mars ~]# bash [root@mars ~]# echo $nameVBird's name <==出现了[root@mars ~]# exit <==退出
什么是子进程呢?也就是说在目前的这个 shell 的情况下,再去打开另一个新的 shell,新的那个 shell 就是子进程。一般情况下,父进程的自定义变量是无法在子进程内使用的。但是通过 export 将变量变成环境变量后,就可以了。
Tips:那么在命令执行中,反单引号( `)这个符号有什么用呢?
比如,我想知道每个 crontab 相关文件名的权限,就可以这样做:ls -l `locate crontab`
变量的有效范围
之前我们提到父进程定义的变量不能被子进程所得知,除非使用 export ,现在我们就来说说父进程与子进程的概念:
子进程仅会集成父进程的环境变量,子进程不会继承父进程的自定义变量。所以我们才需要 export,有的地方也提到全局变量和局部变量,我们大致可以认为。环境变量就是全局变量,自定义变量就是局部变量。
变量键盘读取、数组与声明
读取:read
范例1:让用户由键盘输入内容,将该内容变成名为 atest 的变量[root@mars ~]# read atestThis is a test. <==此时光标就在等待你输入[root@mars ~]# echo $atest This is a test. <==刚刚输入的内容已经变成了一个变量
declare / typeset
declare / typeset 是一样的功能,就是声明变量的类型。如果使用 declare 后面并没有接任何参数,那么 bash 会主动列出所有的变量名称和内容,和 set 一样。
[root@mars ~]# declare [-aixr] variable选项与参数:-a:将后面名为 variable 的变量定义为数组(array)类型-i:将后面名为 variable 的变量定义为整数数字(integer)类型-x:与 export 相同-r:将变量设置成为 readonly 类型,该变量不可被改变内容,也不能重设范例1:让 sum 进行 100+300+50 累加结果[root@mars ~]# sum=100+300+50[root@mars ~]# echo $sum100+300+50 <==并没有帮我们进行计算,因为这是文字类型的变量[root@mars ~]# declare -i sum=100+300+50[root@mars ~]# echo $sum450 <==得到了正确的结果
变量默认为字符串,所以不指定变量类型,则 1 + 2 为一个字符串而不是计算式。bash中的数值运算,默认最多仅能到达整数类型,所以1 /3 结果是 0。
范例2:让 sum 变成非环境变量的自定义变量(以用declare -xr sum 变为了环境变量和只读)[root@mars ~]# declare +x sum <==将 - 变成 + 可以进行取消操作[root@mars ~]# declare -p sum <== -p 可以单独列出变量类型declare -ir sum="450" <==只剩下了i,r类型
有趣的是,如果你不小心设置了某个变量的只读属性,你只有注销再登录才能复原该变量的类型。
数组:array
在 bash 中,数组的设置方式是 var[index] = content,目前bash提供的是一维数组:
#设置一个数组[root@mars ~]# var[1]="small min"[root@mars ~]# var[2]="big min"[root@mars ~]# var[3]="nice min"[root@mars ~]# echo "${var[1]},${var[2]},${var[3]}"small min,big min,nice min#数组的读取建议用${数组}的方式来读取
变量内容的删除、替代与替换
变量内容的删除
#先让小写的 path 设置得与 PATH 内容相同,便于实验[root@mars ~]# path=${PATH}[root@mars ~]# echo $path /usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin范例1:假设我不喜欢 kerberos,如何操作[root@mars ~]# echo ${path#/*kerberos/bin:}/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
上面的这个例子,我们可以详细地来剖析一下它:
${variable#/*kerberos/bin:}
这个 $ 是关键字,用在删除模式是必须的
${variable#/*kerberos/bin:}
这个变量原本的名称,比如我们这里写的 path
${variable #/*kerberos/bin:}
这就是重点,代表从变量内容的最前面开始向右删除,且仅删除最短的那个
${variable#/*kerberos/bin:}
代表要被删除的部分,由于 # 代表由开头开始删除,所有这里由开始的 / 写起
* 通配符,一直匹配到/kerberos/bin为止
从上面的范例我们可以看出,path这个变量被删除的内容如下所示:/usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
接下来继续看 # 的功能:
范例2:删除前面的目录,保留后面的一个[root@mars ~]# echo ${path#/*:}/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin#由于一个 # 仅删除最短的那个
用删除线来看是这样:/usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
[root@mars ~]# echo ${path##/*:}/root/bin#一个 # 变成 ## 之后,它变成了删除最长的那个
用删除线来看是这样:/usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
所以我们可以发现删除的规则:
- #:符合替换文字的“最短的”那一个
- ##:符合替换文字的“最长的”那一个
前面提到的是从前向后,那么从后向前删除呢?其实就使用百分比(%)符号,就可以从后往前删除了,规则和 # 是一致的。
变量内容的替换
变量的替换也很好理解:
范例3:将 path 的变量 sbin 替换成大写的 SBIN[root@mars ~]# echo ${path/sbin/SBIN}/usr/kerberos/SBIN:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin#关键在与两个斜线,两个斜线中间的是旧字符#后面的是新字符,所以结果就出现了上述的情况(只有一个SBIN被修改)[root@mars ~]# echo ${path//sbin/SBIN}/usr/kerberos/SBIN:/usr/kerberos/bin:/usr/local/SBIN:/usr/local/bin:/usr/SBIN:/usr/bin:/root/bin#如果是两条斜线,那么所有的符合条件的都会被替换
总结一下前面的各项:
变量的测试与内容替换
范例1:测试一下是否存在 username 这个变量,若不存在则赋值内容为 root[root@mars ~]# echo $username <==由于出现空白,所以 username 可能不存在,也可能是空字符串[root@mars ~]# username=${username-root}[root@mars ~]# echo $usernameroot <==因为 username 没有设置,所以主动赋给root的内容[root@mars ~]# username="mars name" <==主动设置内容[root@mars ~]# username=${username-root}[root@mars ~]# echo $usernamemars name <==因为已经设置过,所有不会用root替代
上面的范例中,重点在于减号“ - ”后面接的关键字,我们可以这样理解:
new_var=${old_var_content}
新的变量,主要用来替代旧变量
new_var=${old_var_content}
这是本例中的关键字,必须要存在
new_var=${old_var-content}
旧的变量,被测试的选项
new_var=${old_var-content}
变量的内容,在本例中,是给未给予变量的内容
不过这还是有点问题,因为 username 可能被设置为空字符串。这样的话,你还可以通过这种方式:
范例2:若 username 未设置或为空字符串,则将 usernmae 内容设置为 root[root@mars ~]# username=""[root@mars ~]# username=${username-root}[root@mars ~]# echo $username <==因为 username 被设置为空字符串,所以还是保留[root@mars ~]# username=${username:-root}[root@mars ~]# echo $username root <==加上“:”后若变量内容为空或者是未设置,都能够以后面的内容替换
命令别名与历史命令
alias
当我们的惯用命令很长的时候,我们可能希望通过某种方式让它便于输入。这就是命令别名,比如,在 Windows 中清屏是 “cls”,而 Linux 中是 “clear”,那我们其实可以通过别名的方式让 cls 同样可以使用:
[root@mars ~]# alias cls="clear"#或者其他的命令,比如删除[root@mars ~]# alias rmf="rm -f"#我们如何看目前有哪些命令别名呢[root@mars ~]# aliasalias cls='clear'alias cp='cp -i'alias egrep='egrep --color=auto'alias fgrep='fgrep --color=auto'alias grep='grep --color=auto'alias l.='ls -d .* --color=auto'alias ll='ls -l --color=auto'alias ls='ls --color=auto'alias mv='mv -i'alias rm='rm -i'alias which='alias | /usr/bin/which --tty-only --read-alias --show-dot --show-tilde'
至于要取消别名,就用 unalias,比如unalias cls
历史命令:history
直接输入 histroy 就可以看到我们曾经执行的命令,默认是保存1000条。我们来看看它的参数:
[root@mars ~]# history [n][root@mars ~]# history [-c][root@mars ~]# history [-raw] histfiles选项与参数:n :数字,列出最近的 n 条命令-c:将目前 shell 中的所有 history 清除-a:将目前新增的history命令新增入histfiles,若没有则默认写入~/.bash_history-r:将 histfiles 读入 history-w:将 history 写入 histfiles
这里着重讲一下,history的另一个作用:
[root@mars ~]# !number[root@mars ~]# !command[root@mars ~]# !!参数:numbner:执行第几条命令command:由最近的命令向前搜索命令串开头为 command 的命令并执行!! :执行上个命令,相当于 ↑+Enter[root@mars ~]# history 66 man rm 67 alias 68 man history 69 history[root@mars ~]# !66 <==执行第66条命令[root@mars ~]# !! <==执行上一个,即本例中的 !66[root@mars ~]# !al <==执行最近的以 al 开头的命令(即本例中的第 67 个)
Tips:同一个账号同时多次登录的 history 写入问题
假设多个bansh同时写入,还是都是root。那么其实这些记录一开始都是写在内存中的,注销的时候才会更新。所以,最后一个注销的才会是最后写入的数据(其实都有记录,只是被覆盖了)
- Linux学习(13)--初识bash shell
- linux 基础学习之三:bash shell初识 上
- linux 基础学习之三:bash shell初识 下
- 初识linux(八)--bash shell 的功能
- linux bash shell 学习
- Linux Bash Shell学习(十六):数组
- linux的shell(bash)脚本学习
- Linux学习之八(shell、bash)
- Linux Bash Shell 学习笔记
- linux bash shell学习笔记
- Linux学习之Bash Shell
- 【Bash百宝箱】Linux shell学习
- 【Linux学习】之 Shell初识
- Linux Bash Shell学习(一):开始看书《Learning the bash Shell,3rd》
- Linux Bash Shell学习(二):目录和通配符
- Linux Bash Shell学习(四):编辑命令
- Linux Bash Shell学习(六):设置环境参数
- Linux Bash Shell学习(十四):命令行选项
- Lotus Notes登录后无法进入邮件,一直处于“正在加载,请稍候” 解决办法!!!
- win7命令学习集锦
- TensorFlow 实现人脸识别
- 接受int形参(double,,等等)返回int(...);并且一个vector对象保存指向这些函数的指针;进行加减乘除;输出结果
- Gradle学习文档
- Linux学习(13)--初识bash shell
- vs调试时查看stlport 变量内容
- mybatis关系映射之一对多和多对一
- 日/夜模式切换
- TensorFlowOnSpark 初体验
- 堆和栈的区别(写的非常好)
- 解决webstorm下的npm一直显示更新索引,引起的卡顿问题
- 【burpSuite】浏览器设置代理后无法访问https
- JVM学习-------内存分配