学习Shell脚本第一步!
Linux下使用的Shell标准Shell是bash, 这是BShelll家族的一员, BSD.Unix下的标准SHell是CShell.
BShell(Bourne Shell)主要包括sh.ksh.Bash.psh.zsh, Cshell主要包括csh, tcsh.
Bash的基础功能
命令别名和快捷键
在Shell中使用alias可以看到当前的别名, 有些命令敲起来很长, 很不方便, 所以就建立一个映射.
一个最典型的例子就是: ll = ll -l --color=auto
.
临时更改SHell别名可以直接在alias中设置, alias sth.='another th'
.
这样的设置在重启机器后就会失效, 如果想要永久设置就在.bashrc下.
编辑后,该文件不会立即生效.这里使用source
来使得系统重新载入.
接下来我来说一下Liuux中命令的生效顺序:
1 | 第一顺位: 执行用绝对路径或相对路径执行的命令 |
下面说一些超常用的快捷键:
Ctrl + c terminate current order.
Ctrl + l clear screen
Ctrl + a move cursor to the head of the line
Ctrl + e move cursor to the end of the line
Ctrl + u delete from the head of the line to the current position of the cursor
另外补充一个: 使用 ALT+. 可以复制上一条命令的最后一个单词, 这里说的单词是指命令的词. ( 使用远程连接的话, 需要使用Esc来代替ALT, 或者可以想个办法做mapping.
历史命令
Bash是可以查看历史命令的, 在早期的BShell是没有历史命令功能的.
查看历史使用history
命令, 和这个关联的文件时.bash_history
, 我们知道使用history加上-c
参数可以清空历史命令.
事实上, 历史仍然保存在文件中, -c
仅仅是清空Buffer中的命令, 而如果想要彻底删个干净就要在-c
之后再加上-w
执行一遍.-w
的意思是将缓存的历史命令写入到文件中(覆盖).,
在我们每次注销的时候, 系统会自动执行-w
.
另外, 历史命令还有这样的使用方法.
1 | !! 重复执行上一条命令 |
在Shell中使用Tab键进行命令补全, 这是一个很重要的功能, 它不仅大大加速我们的命令输入, 而且还有一定的查错能力.
输出重定向
首先要明确的是三个标准输入输出:
1 | 键盘 /dev/stdin 0 标准输入 |
命令的输出默认当然就是显示屏幕上, 也就是标准输出1.
但是Bash是可以重定向输出流的,像这样
1 | ifconfig > test.log |
命令输出 > / >> 仅能保存正确的输出, 如果遇到错误的情况还是会输出到屏幕上, 这就是因为标准错误输出和标准输出是两个东西.
参见下表:
类型 | 符号 | 作用 |
---|---|---|
标准输出重定向 | Command > file | 覆盖方式 |
标准输出重定向 | Command >> file | 追加方式 |
标准错误输出重定向 | COOMAND 2>file | 覆盖方式 |
标准错误输出重定向 | COOMAND 2>>file | 追加方式 |
注意:标准错误输出重定向的时候,>>和文件之间是没有空格的!一旦出现空格,重定向就会失效
但是,仔细想一下2>/2>>
这种我们根本就不会使用到, 因为如果已经知道命令是错的, 为什么我还要执行呢?
所以下表更有参考价值:
类型 | 符号 | 作用 |
---|---|---|
标准错误输出和正确输出重定向 | 命令 > 文件 2>&1 | 覆盖方式 |
标准错误输出和正确输出重定向 | 命令 >>文件 2>&1 | 追加方式 |
标准错误输出和正确输出重定向 | 命令 &>文件 | 覆盖方式 |
标准错误输出和正确输出重定向 | 命令 &>>文件 | 追加方式 |
标准错误输出和正确输出重定向 | 命令>>文件1 2>>文件2 | 追加方式 |
其中,13和24等价.
另外, 如果不想将输出输出到文件中, 可以重定向到”黑洞”中, 也就是/dev/null
, 这个文件就像是路由黑洞一样吃进去就没反应了, 或者类比成Windows下的回收站.
这个文件就是可以理解成Linux预置的垃圾桶, 在一些命令/脚本执行过程中发生的一些无关紧要的错误, 我没有必要将其显示出来. 而是可以直接丢弃掉.
关于输入重定向, 我们以wc
来举个例子, wc
可以统计输入流中的字节数, 单词数, 行数.
1 | wc<anaconda-ks.cfg |
这个意思是anaconda-ks.cfg
文件中, 有148行, 228个单词, 2523个字节.
管道符
首先来说一下多命令执行符这个东西.
同高级语言一样, Shell的对多命令顺序执行的执行符和一些逻辑关联词是一样的.
多命令执行符 | 格式 | 作用 |
---|---|---|
; | 1;2 | 顺序执行, 没有逻辑联系 |
&& | 1&&2 | 逻辑与, 只有1正确执行, 2才会执行 |
ΙΙ | 1 ΙΙ 2 | 逻辑或, 只有1执行不正确, 2才会执行 |
一个简单的综合使用就像是这样
1 | ./abash.sh && echo yes || echo no |
接下来看一下管道符:
|
.
简单的一个竖杠, 可以将命令1的正确输出作为命令2的操作对象.
来看一个简单的小栗子:
1 | netstat -an | grep ESTABLISHED | wc -l |
这个命令组合显示当前已建立的连接数.
通配符
最后来看一下通配符.
通配符 | 作用 |
---|---|
? | 匹配一个任意字符 |
* | 匹配0个或任意, 可以匹配任意内容 |
[] | 匹配中括号内的任意一个字符 |
[-] | 匹配中括号内任意一个字符, -表示一个范围 |
[^] | 逻辑非, 匹配不是中括号内的一个字符 |
接着再来说一下Bash中的特殊字符:
符号 | 作用 |
---|---|
‘’ | 在单引号中的特殊符号都失去意义 |
“” | 除了”$”, “`”, “", 其他都失去特殊含义 |
`` | 调用系统命令, Bash中会优先执行 |
$() | 等价于``,引用系统命令 |
# | 注释 |
$ | 调用变量的值 |
\ | 转义字符 |
其中, 推荐使用 $() 来代替 `, 因为更清晰.
在开始进行Shell编程前, 必须还要了解一些环境变量,位置参数变量以及预定义变量.
我们已经知道如何去定义一个变量: a=4
.
但是这样定义的变量是不能在Shell间通用的,现在就可以引入环境变量的概念了.
环境变量是作用于系统的一类变量, 只要在声明时加上export
关键字就可以生效了.
使用set
查看所有的系统变量, 使用env
仅仅查看环境变量.
接下来说一下位置参数变量, 其实这个就像是Python
的sys.argv
, 获取脚本参数的变量.
有这些位置参数:
参数 | 作用 |
---|---|
$n | n是数字, 0代表本身, 1-?就是后面的参数 |
$* | 命令行中的所有参数(作为整体) |
$@ | 命令行中的所有参数(作为单独的部分) |
$# | 参数的个数(不包括脚本本身) |
最后, 就是一些预定义变量了.
主要有三个:
参数 | 作用 |
---|---|
$? | 返回上次命令执行的状态 |
$$ | 当前进程的PID |
$! | 后台运行的最后一个进程的PID |
接下来开始进行Shell的学习吧!
变量
之前说过了如何去声明和打印一个变量, 但要知道的是, Linux中的所有变量默认都是字符串型的.
也就是说:
1 | [root@localhost ~]# a=11 |
这样就没办法进行数值运算了.所以先来学习一下怎么声明种类.
使用declare来声明变量类型,语法结构和支持的类型是:
1 | declare [+/-][Opt.] 变量名 |
举几个例子:
1 | [root@localhost ~]# aa=11 |
或者声明数组变量:
1 | [root@localhost ~]# movie[0]=a |
现在可以告诉你啦!
之前使用的export
实际上调用的就是declare
的-x
选项, 不信的话你可以试试declare -p
, 接着你就会看到大部分的系统环境变量都是declare -x
.
最后再看一下,只读属性(-r)
, 请注意:不要随意添加只读属性, 因为只读的属性是不可删除 不可改变 不可取消的.
现在就来学习数值运算了.
虽然之前说的声明类型同样可以进行数值运算, 但是这还是有点麻烦的.
所以当进行表达式(expression)运算时, 使用expr
来进行运算.
e.g:
1 | [root@localhost ~]# aa=11 |
注意!expr后面的运算符两侧必须要加空格否则会失效
这就很好敲了? 相信你一定满脸MMP..
是的..这个命令更难敲.
所以来看一下这个:
1 | [root@localhost ~]# aa=22 |
这样就更好记了.
那么Shell支持哪些运算呢?
按照优先级从高到低:
运算符 |
---|
单目正负 |
逻辑非.按位反 |
乘除 取模 |
加减 |
左移 右移 |
比较运算 |
按位运算 |
逻辑运算 |
赋值及运算赋值符 |
继续下去..我们来看一下变量测试
这个东西只有Shell中才有, 其他语言中是没有的.
好吧..这个东西主要是用来脚本调优.(真的我觉得没什么用)
下一个表来看,其实语法上没什么难的..
好了变量测试就先这样吧..