目录
1.了解Shell
2.Shell的变量功能
本地变量
环境变量
位置变量
3.系统的环境变量
4.变量的键盘读取、数组与宣告: read, array, declare
5.变量内容的删除、取代与替换
6.命令的别名设置
7.Bash Shell 的操作环境
7.4.终端机的环境设定: stty, set
7.5.通配符与特殊符号
7.6.数据流重导向
7.7.命令执行的判断依据: ; 和 && 和 ||
7.8.管道命令(pipe)
截取指令: cut, grep
tee指令:双向重定向
7.9.排序命令:sort,wc,uniq
8.字符转换命令: tr, col, join, paste, expand
8.1.tr命令
8.2.col指令和expand指令
8.3.paste 命令
8.4.join命令
8.5.分割命令: split
8.7.关于减号 - 的用途
1.1.什么是Shell?
翻译成中文shell就是外壳的意思,那他有什么用?我们知道管理整个计算机硬件的其实是操作系统的核心 (kernel),这个核心是需要被保护的,同时操作系统给会给出一个接口然你来控制这个操作系统的某些进程,而这个沟通的媒介就是Shell,在Linux系统中可能会内嵌很多种Shell,他们的目的都是和操作系统进行通信,常用的是Bash,这个Shell中的一种。
1.2.shell的工作流程
我们知道不管我们执行什么命令,到最后都是由硬件来执行这个任务的,那他的运作流程是什么呢?加入我们需要播放音乐的话,当我们下达指令,计算机需要去做什么?
1. 硬件:当然就是需要你的硬件有『声卡芯片』这个配备,去驱动你的喇叭;
2. 核心管理:操作系统的核心可以支持这个芯片组,当然还需要提供芯片的驱劢程序;
3. 应用程序:需要使用者 (就是你) 输入发生声音的指令!
1.3.如何使用shell呢?
shell是一个看不到,摸不着的东西,当使用KDE桌面时,可以打开一个终端,这个终端是一个软件,它可以帮我们连接到shell,但是注意,这个终端并不是shell,它只起一个连接的作用
1.4.Linux系统中存在哪些Shell((以 CentOS 5.x 为例)?
可以通过查看档案:/etc/shells 查看当前系统Shell的种类,默认使用的是bash
/bin/sh (已经被 /bin/bash 所取代)
/bin/bash (就是 Linux 预设的 shell)
/bin/ksh (Kornshell 由 AT&T Bell lab. 发展出来的,兼容于 bash)
/bin/tcsh (整合 C Shell ,提供更多的功能)
/bin/csh (已经被 /bin/tcsh 所取代)
/bin/zsh (基于 ksh 发展出来的,功能更强大的 shell)
如果你想切换到某个shell直接在命令行上输入shell的名字就行,例如:切换到ksh
1.6.为什么使用shell?
1.shell使用的是命令行,处理速度快。
2.远程管理如果使用命令的话,传输数据就小,控制流畅。
3.shell支持大量的快捷键,提高用户的效率。
1.7.shell命令和系统命令
shell是系统在安装的时候自动安装上去的,查找一个命令在哪的话,使用wihch 命令,比如 which ls
找一下 cd 这个命令的位置,命令:which cd,在PATH环境变量下,找不到cd这个命令,那为什么我们可以执行cd这个命令进行目录进行跳转呢?
举个例子,使用window系统来演示,我们现在直接的cmd命令行直接输入:qq这个命令,提示说找不到这个命令,当我们进入到qq安装路径下的文件时,然后再次执行这个命令时,系统就打开了一个qq的登陆接口。所以说这个命令是我在安装qq之后生成的,如果不安装这个软件的话也不会有这个命令,所以我们系统原本没有cd这个命令,但是安装了shell之后,cd是shell内置的命令,不是系统的命令。
如何查看cd命令是否属于shell内嵌的命令?
使用命令:type cd
2.1什么是变量?
就是让某一个特定字符串代表不固定的内容就是了,比如:a=5,左边是一个可以变化的字符,右边是一个固定的数字。
使用变量的好处就是可以让系统的运作流程变得简单。
2.2.如何使用变量
本地变量
- 本地变量的特点时,只会在当前的Shell起作用不会,影响带其他的子shell
定义一个本地变量的方法:变量名=值
注意:变量名可以由字母、数组、下划线组成,不可以使用数字开头,等号两边不要有空格。
例子1:
定义一个本地变量,a=20 。 注意:打印的时候不加 $ 字符,会吧a当作普通字符来使用,打印出来的就是a这个字符。
取消一个变量的设定:unset 变量名
取消变量a的设定:
例子2:
本地变量的设定只会在当前shell起作用,不会影响到其他的子shell,现在在一个shell中创建一个变量b然后打开另一个shell看一下这个本地变量是否还存在?
环境变量
- 环境发量可以帮我们实现很多种功能~包括家目录的变换、提示字符的显示啊、执行文件搜寻的路径等等。
- 环境变量的特点是它会影响到所有的子shell
如何定义一个环境变量?
方法:export 变量名=值
注意:如果已经设定了一个本地变量a,那么使用export a ,可以把这个本地变量变成一个环境变量。
例子:
环境变量可以影响到所有的子shell,在父shell中新建一个变量c,给其复制20,然后打开一个子shell,然后打印这个环境变量:
2.3如何查看所有的变量?
使用命令:set , 就会显示系统所有的变量,包括本地和环境变量。
使用命令:env
提示:使用export 和 export -p和set都可以查看系统的环境变量
可以看到使用export查看环境变量显示时多了一个词:declare
- declare / typeset 的用法
declare 与 typeset 是一样的功能,就是在『宣告变量的类型』。如果使用 declare 后面幵没有接任何参数,那么 bash 就会主动的将所有的变量名称与内容通通列出来,就好像使用 set 一样。
命令:declare
语法:declare [-aixr] variable
选项及其含义
选项 含义 -a 将后面名为variable的变量定义成数组(array)的类型。 -i 将后面名为variable的变量定义成整数数字(integter)类型 -x 用法与export一样,将后面的variable变成环境变量。 -r 将变量设定为readonly类型,该变量的内容将不可被更改,也不可取消(unset)该变量 +x 可以将环境变量转变为位置变量
位置变量
- 当我们在写脚本的时候这个位置变量很重要
例:1:
写一个脚本文件,命令为test.sh,使用vim打开,编辑脚本文件
运行脚本然后给这个程序8的参数:
例子2:
直接使用set设置位置变量的值,使用命令,set 1 2 3 4 5 6 7 8,然后打印位置变量的值看一下:
试着设的长一点,使用命令:set 1 2 3 4 5 6 7 8 9 a b c d e,当打印第11个位置变量的时候好像出错了
注意:如果使用命令:echo $11,会首先显示$1的内容然后再次显示$1的内容,同时打印出两个11了,咋看起来是11.所以当位置变量的数字大于两位数的时候,加一个大括号,比如:echo ${11}
那么 :$0 代表什么意思呢?$#呢?$*呢?
解释:$0 代表的是整个程序的名字,$# 代表的是未知变量的个数,$* 表示所有的位置变量
例子3:
修改test.sh这个脚本程序,测试 $0,$#,$*的功能
编辑后保存,运行脚本程序:
代表用户的家目录。可以用cd 命令去到我们的家目录下,使用cd命令不加任何的参数既可以回到家目录。不同的用户拥有唯一的家目录,其实就是取用这个变量的值。
记录当前系统所用的shell
这个与历史命令有关, 我们曾经下达过的指令令可以被系统记录下来,而记录的『笔数』则是由这个值来决定。
当我们使用 mail 这个指令在收信时,系统会去读取的邮件信箱档案 (mailbox)。
执行文件搜寻的路径~目录与目录中间以冒号(:)分割, 由于档案的搜寻是依序由 PATH 的变量内得目录来查询,所以,目录的顺序也是重要。
语系数据,很多讯息会用到它, 丼例杢说,当我们在启动某些 perl 癿程序语言档案时,他会主动的去分析语系数据文件, 如果发现有他无法解析的编码语系,可能会产生错误!一般来说,我们中文编码通常是 zh_TW.Big5 或者是 zh_TW.UTF-8,这两个编码偏偏不容易被解译出来,所以,有癿时候,可能需要修订一下语系数据。
就是『随机数』的变量!目前大多数的 distributions 都会有随机数生成器,那就是 /dev/random 这个档案。 我们可以透过这个随机数档案相关的变量 ($RANDOM) 来随机取得随机数值。在 BASH 的环境下,这个 RANDOM 变量得内容,介于 0~32767 之间,所以,你叧要 echo $RANDOM 时,系统就会主动的随机取出一个介于 0~32767 的数值。万一我想要使用 0~9 之间癿数值呢,利用 declare 宣告数值类型。
这个就是显示我们命令提示符,当我们执行一个命令之后,在#号前面都有一些提示信息,比如你当你当前所在路径等等,这些东西通过PS1变量你可以自行设定的。
设定符号的意义:
符号 | 含义 |
\d | 显示星期、月、日的日期格式,如Mon Jun 6 |
\H | 完整的主机名,如:www.yuan.com |
\h | 仅仅取主机名在第一个小数点之前的名字,如:www |
\t | 显示时间24小时格式:HH:MM:SS |
\T | 显示时间12消失格式:HH:MM:SS |
\A | 显示时间24消失格式:HH:MM |
\@ | 显示时间12消失格式:am/pm 样式 |
\u | 目前使用者账号,如:yuangege,或root |
\v | bash版本信息 |
\w | 完整的工作目录,由根目录开始,家目录以~取代 |
\W | 利用basename函数获取工作目录名称,仅列出最后一个目录名 |
\# | 当前下达的是第几个指令 |
\$ | 提示字符,如果是root时,提示符为#,否则就是$ |
例子:看一下当前我们提示符的设定:
可以看到显示的样式和设定的是一模一样的。
我们也可以去更改一下环境变量PS1的值,我们让他显示在最前面显示一个时间,显示完整主机名,然后显示完整的工作目录。
使用命令:PS1="[\t @\u@\H \w]\$"
当我们写程序的时候一行不够写,只需要输入一个反斜杠,自动就会跳入到下一行继续这个命令,而在继续命令之前还有一个提示符,这个提示符即使PS2设定的,看一看默认的提示符是什么?
同样我们也可以去修改这个提示符,把这个提示符改成:————》
使用命令:PS2="——》"
4.1.read
作用:用来读取键盘的变量。
语法:
read [-pt] variable
选项
选项 | 含义 |
-p | 后面可以接提示符 |
-t | 后面接等待的描述,不会一直等待用户输入 |
如果read后面什么都不跟,直接加上变量的名字,底下就会有一个空白行让你输入,按回车就等于是给这个变量赋值了。
当系统遇到read,程序就不会往下走了,等待用户输入,才往下执行。
例子:
使用命令:read aa ,然后输入一段数组,回车
如果输入命令,什么都不跟的话是赋值给哪个变量,那就是默认的变量:REPLY
比如:输入read 然后输入88888,回车,再打印REPLY的值
例子2:
read 用作脚本的输入:
新建一个:test.sh的脚本,然后使用vim编辑器编辑
方式一:
方式二:
方式三:
执行这个脚本:
4.2.数组 (array) 变量类型
数组和变量的意思是一样的,只不过数组可以连续储存多条数据,然后把这些数据有规律的储存在数组里面,当你获取一组网络数据时,可以根据你的需要获取或者分析你想要的部分。
数组的设定定方式是:array=(a b c d)
例子:
定义数组的方式一:
使用命令:array=(a b c d)
解释:定义一个数组,数组的名字是array,数组的成员有四个,第一个是a,第二个是b,第三个是c,第四个是d,想要获取数组第一个的值使用命令:echo ${array[0]}
一次性打印数组的所有元素,使用命令:echo ${array[*]} 或 echo ${array[@]}
查看数组的个数以及下标,使用命令:echo ${!array[*]} ,查看数组的元素个数,使用命令echo ${#array[*]}
4.3.declare / typeset
declare 和 typeset 是一样的功能,就是在『宣告变量的类型』
命令:declare
语法:
declare [-aixr] variable
选项:
选项 | 含义 |
-a | 将后面名为variable的变量定义成数组(array)类型 |
-i | 将后面名为variable的变量定义成为整数数字(integer)类型 |
-x | 用法和export一样,将后面的variable变成环境变量 |
-r | 将变量设定为readonly类型,该变量的内容不可被更改,也不能unset |
+x | 把环境变量取消 |
例子:
定义个环境变量a。
注意事项:
单引号和双引号的使用:
反引号的使用
5.1.变量和内容的删除
例子:
先建立一个变量path,然后复制环境变量PATH里面的内容来做实验:
那么现在path的内容是:
/opt/xtensa-lx106-elf/bin:/usr/local/sbin:/usr/local/bin:
/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
定义一个变量:r,它的值等于:path # * /sbin,即命令:r =$ {path # * /sbin}
解释:如果只有一个#号,代表从最近的一个关键字,删除到头,删除path里面所有的usr/sbin 前面的东西,然后复制给 r 这个变量。那么是如下这种结果。
结果:
共有三个关键词:/sbin
/opt/xtensa-lx106-elf/bin:/usr/local/sbin:/usr/local/bin:
/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
从最近的那个开始删除,结果如下:
/opt/xtensa-lx106-elf/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
如果使用命令:r = {path ## * /sbin}
解释:如果有两个##的话,代表从最远关键字的一个开始删除,删除到开头,删除/sbin前面的东西,然后赋值给r变量
结果:
共有三个关键词:/sbin
/opt/xtensa-lx106-elf/bin:/usr/local/sbin:/usr/local/bin:
/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
从最远的那个开始删除,结果如下:
/opt/xtensa-lx106-elf/bin:/usr/local/sbin:/usr/local/bin:
/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
使用#号键从头开始删除,那么有没有从尾开始删除的呢?
答案肯定是有,使用的符号是:%
例子:
接着上面的例子,使用命令:r =$ {path% /sbin*}
解释:注意*在后面,代表的是从/sbin开始,*代表后面是什么都无所谓,只有一个%符号,代表从尾网头找,找到最近一个关键字然后从尾删除到最近的一个关键词,结果如下:
结果:
共有三个关键词:/sbin
/opt/xtensa-lx106-elf/bin:/usr/local/sbin:/usr/local/bin:
/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
从最近的那个开始删除,结果如下:
/opt/xtensa-lx106-elf/bin:/usr/local/sbin:/usr/local/bin:
/usr/sbin:/usr/bin:
/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
那么从尾删除到最前的一个关键字使用的是:两个%%
使用命令:r =$ {path%% /sbin*}
结果:
共有三个关键词:/sbin
/opt/xtensa-lx106-elf/bin:/usr/local/sbin:/usr/local/bin:
/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
从最近的那个开始删除,结果如下:
/opt/xtensa-lx106-elf/bin:/usr/local
/sbin:/usr/local/bin:
/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
5.2.变量内容的替换
我们可以发现,当我们打印一个变量的值时,当这个变量不存在时,它显示的是空值,当这个变量存在,且设置一个变量为空值时,打印结果都是一样的,这样就没有办法去判定这个变量是否存在了。
例子1:
那如何判断一个值是否存在或者是被定义?
方式一:只能判定一个变量是否存在
使用命令:r = ${a-"unexitstant"}
解释:如果说a这个变量存在或者定义过,那么r的值就等于a的值,如果a这个变量不存在那么r的值就是双引号的内容即为:unexitstant。
方式二:判断一个变量是否存在,如果不存在和空值都是一个结果
使用命令:r = ${a:-"unexitstant"}
解释:如果说a这个变量存在或者定义过,那么r的值就等于a的值,如果a的为空值的话也会赋值unexitstant给r,如果a这个变量不存在那么r的值就是双引号的内容即为:unexitstant。
方式三:
使用命令:r = ${a:="unexitstant"}
解释:如果a这个值存在的话把a的值赋值给r,如果a这个值不存在或者是空值的话,把unexitstant 赋值给a这个变量。
方式四:判断一个变量是否被定义或是否为空值
使用命令:r = ${a:?"unexitstant"}
解释:如果变量a不存在或者是一个空值,就会有一个警告
方式五:判断一个变量是否存在或者非空值
使用命令:r = ${a:+"exitstant"}
解释:如果变量a存在的话,就把exitstant 赋值给变量r,如果没有被定义或者是空值的话,打印出来的r也是空的。
命令别名设定: alias, unalias
解释:命令的别名顾名思义就是,就像是小名一样,比如有一个人名字叫王二,他的小名叫狗蛋,不熟悉王二的人就会叫他的真名,熟悉的人(给它取别名的人啦)也可以叫他狗蛋,这样叫的结果都是一样的,王二知道这都是在叫他。
别名设置方法:
alias 别名 = "命令"
解释:此时这个别名就和这个命令是等效的了
例子:
如果需要看系统的网卡配置的话,我们需要输入命令:ifconfig ,如果你想简便一点你也可以给它取一个别名bb,
使用命令:alias bb = "ifconfig"
查看系统的所有别名,使用命令:alias
取消别名,使用命令:unalias 别名
7.1.路径与指令搜索顺序
在第6节的时候,知道有alias命令别名的东西,一个命令可以有很多种别名,他们执行的顺序是什么,例如ls可能有很多条别名,那到底系统执行这些命令顺序的依据是什么?
例子:
比如现在执行命令:echo aaaaaaaaa,系统打印出aaaaaaa,然后自动有一个换行符,那么可以使用别名当我们调用echo的时候取消这个换行符,命令:alias echo = "echo -n",然后再打印输出echo aaaaaaaaaaaaaa,发现没有换行了。那意味着执行了别名这条命令了,为什么这个顺序比echo优先执行?
那么当我们使用ls这个命令的时候,是使用 :/bin下面的ls呢,还是alias别名的ls,还是通过系统路径PATH下搜索的ls,还是bash内建的ls呢?
查看命令的执行顺序使用命令:type -a 命令
查看echo的命令执行顺序,使用命令:type -a echo
7.2.bash 系统登陆提示信息: /etc/issue, /etc/motd
issue各代码的意义 | |
\d | 本地端口的日期 |
\l | 显示第几个终端接口 |
\m | 显示硬件等级 |
\n | 显示主机的网络名称 |
\o | 显示域名 |
\r | 显示操作系统版本(相当于uname -r) |
\t | 显示本地端时间 |
\s | 操作系统名称 |
v | 操作系统版本 |
注意:登陆后的信息各代码意义和登陆前的参数是一样的。
例子:
切换到Ubuntu的tty3的控制台(快捷键:Ctrl+Alt+F3),然后可以看到如下的提示信息:
登陆之后也有提示信息:
如何修改这些提示信息?
修改登录之前的提示信息,修改:/etc/issue 的内容,使用命令查看:vim /etc/issue
可以看到默认只有一行,从代码的意义可以看出,显示出主机网络名称和所在终端的位置
我们也可以修改一下他的登陆信息:
修改如下:
然后退出,重新登陆看到如下的界面:
提示:登陆后的信息只需要编辑:/etc/motd 修改即可。
7.3.bash的环境配置文件
当我们一登录linux系统,还没有定义变量时,就有一堆系统变量可以用,当你注销了系统之后,这些变量就会消失,这是为什么呢?
这是因为系统有一些环境配置文件的存在。
- login 与 non-login shell
1.当我们没有登陆系统之前(还么有输入正确的用户名密码之前),我们使用shell称为:login shell ,当我们已经使用账户密码登陆之后使用的shell,称为:non-login shell,此时无论打开几个终端都是不需要输入用户密码的。
2.介绍login 与 non-login shell 原因,这个因为在这两个shell下读取的配置文件是不一样的
7.3.1.login shell
一般来说login shell 只会读取两个配置文件:
1./etc/profile:这是系统整体的设定,不建议修改
2.~/.bash_profile 或者 ~/.bash_login 或 ~/.profile:属于使用者个人设定,你要改自己的数据,就写入这里!
我们系统本身拥有很多的快捷键,比如退格键驾驶删除数据,Ctrl+c就是终止一个命令的执行等等,这些都是在哪里设定的呢
使用命令: stty -a ,查看系统的一些按键的设置,可以看到有很多的快捷键
提示:如果出现 ^ 表示 [Ctrl] 那个按键的意思。举例子, intr = ^C 表示使用 [Ctrl] + c 的快捷键。
几个重要参数的含义:
eof : End of file 的意思,代表『结束输入』。
erase : 向后删除字符,
intr : 送出一个 interrupt (中断) 的讯号给目前正在 run 的程序;
kill : 删除在目前指令列上的所有文字;
quit : 送出一个 quit的讯号给目前正在 run 的程序;
start : 在某个程序停止后,重新启动他的 output
stop : 停止目前屏幕的输出;
susp : 送出一个 terminal stop 癿讯号给正在 run 的程序
set 可以帮我们设定整个指令输出/输入的环境,例如记录历史命令、显示错误内容等等。
命令:set
语法:
set [选项]
选项:
选项 | 含义 |
-u | 启用后,当所使用的变量未设定时,输出错误信息。默认不启用 |
-v | 启用后,信息被输出前,先显示信息的原始内容。默认不启用 |
-x | 启用后,在指令被执行前,显示指令内容(且前面带++符号)。默认不启用,脚本排错常用 |
-h | 与历史明明有关。默认启用 |
-H | 与历史命令有关。默认启用 |
-m | 与工作管理有关。默认启用 |
-b | 与括号 [ ] 的作用有关 。默认启用 |
-c | 启用后,若使用 > 等,若档案存在时,该档案不会被覆盖。默认不启用 |
例子:
但我们使用一个变量的时候,如果他没有定义默认系统不会提示我们这个变量有没有被定义,如果我们需要提示,值需要设定一个-u这个参数。使用命令:set -u
提示:关闭这个功能使用命令:set +u.
通配符符号和含义:
符号 | 含义 |
* | 代表【0到无穷多个】任意字符 |
? | 代表【一定有一个】任意一个字符 |
[ ] | 代表【一定有一个在括号内】的字符(非任意字符),例如[abcd]代表一定有一个字符要是,a,b,c,d中的任意一个。 |
[ - ] | 代表【在编码顺序内的所有字符】,例如 [0-9]代表0到9之间的所有数字。 |
[ ^ ] | 代表【反选选择】,例如[^abc]代表一定有一个字符,除了a,b,c这三个 |
例如:
现在我需要你找出一个文件。
要求:第一个字符必须是字符:[a-z],第二个必须是数字:[0-9],第三个无所谓:?,第四个字符不能是数字:[^0-9],后面是什么都无所谓,文件名的后缀是.mp4。
在计算机怎么表达呢?这是就需要使用通配符,注意,一个中括号匹配一个字符。
现在创建几个文件测试一下:
使用命令: touch bd5465s.mp4 h9e6je8.mp4 v22hsdflk.mp4 addfc5465.mp4
从上图看很明显只有一个是匹配的,那就是:v22hsdflk.mp4 ,第一个是字符,第二个数字,第三个无所谓,第四个必须是非数字,然后后面多长都无所谓,后缀是:.mp4的。
使用命令查找一下:ls [a-z][0-9]?[^0-9]*.mp4
什么是数据流重导向?
如果我们执行一个指令,一般都是默认从键盘输入,然后执行结果从屏幕显示出来,不管执行结果正确与否都会进行输入,这是什么原理呢?
指令的执行情况大致如上图所示。
引入数据重导向:
standard output和 standard error output分别是执行结果正确返回的信息,和执行结果返回的信息,不管信息正确与否,我们都需要把它的信息输出在桌面上。
举例子来说:我们的系统有 /etc/hosts目录, 但却无/etc/yuan, 此时若下达『 cat /etc/hosts /etc/yuan 』这个指令,cat 会进行:
1.标准输出:因为存在、/etc/hosts这个档案,将该档案正确的输入到屏幕上。
2.错误标准输出:因为不存在、/etc/yuan这个档案,在屏幕上显示错误的信息。
我们试着运行一下:
不管是否正确执行都是统统输出到屏幕上,如果数据多的话,就会乱糟糟的不知从何看起,那有没有方法将他们的正确运行结果和错误的运行结果分开呢?
当然可以啊!那就是数据流重导向的功能!数据流重导向可以将 standard output(简称 stdout) 与 standard error output (简称 stderr) 分别传送到其他的档案或装置去,而分别传送所用的特殊字符则如下所示:
1. 标准输入 (stdin) :代码为 0 ,使用 < 或 <<
2. 标准输出 (stdout) :代码为 1 ,使用 > 或 >> ,只能重定向正确的结果
3. 标准错误输出(stderr):代码为 2 ,使用 2> 或 2>> ,只能重定向错误的结果注意:使用 &> ,不管是正确的结果还是错误的都可以重导向到档案里。
例子:
现在想要查看日历,使用命令:cal,如果直接敲命名回车的话,那就是直接输出在屏幕上,如果我想让他数据流重导向到一个档案里面去怎么做呢?
使用命令:cal > 档案名
注意:如果 这个档案不存在的话会自动的新建一个档案的,如果这个档案是存在的,会先清空这个档案的东西,然后再把数据放进去。
现在file1里面已经有文件了,如果此时再次敲一个命令:date > file1,那无疑就会覆盖掉原来的东西,但如果你想保留着里面的东西,然后在这基础之上,添加date的数据呢?
使用命令:date >> file1
解释:两个大于号 >> 把date重定向输出到file1,且保留file1原本的数据内容:
那么错误的信息能通标准输出数据重定向导入到file1这个文件里面去吗?发现错误的信息并不能导入,直接就输出到屏幕上了
如果你想重定向错误的数据,那就得使用错误重定向符,使用:2> 或 2>>
使用命令:aaaaa 2> file1
特殊用法:
使用命令:cal 2> file1 1>&2
解释:cal命令是正确的,原本使用2>是不可以导入的,但是后面多了一个,1>&2 ,就可以实现导入了,意思是,正确的结果向错误一样的导入。
那就有命令让错误的信息像正确那样导入咯。
使用命令:aaaa > file1 2>&1
解释:aaaa命令是不存在的,使用正确的导向符,理论不可以输入到file1上,使用,2>&1 ,把错误的信息像正确的一样导入。
输入重定向:standard input : < 与 <<
以最简单的说法, 那就是『将原本需要由键盘输入的数据,改由档案内容来取代』的意思。
例子1:利用cat指令创建一个档案简单流程
解释:由于在cat 加上了一个输出重定向符 > 之后,file3会主动被建立,输入的内容就是键盘上输入的数据,如果这样的话我们能不能使用文本来代替我们键盘的输入呢,当然任然是新建,而文本是从外部档案输入的。
例子2:
使用cat新建一个档案,然后档案的内容来自于:/etc/hosts档案,其实这跟复制很像,就是把里面的内容复制来,然后重命名一样了。
使用命令:cat > file4
验证一下:
例子3:
使用命令:cat > file2 <<55aa
解释:<< 这个连续两个小于的符号了。 他代表癿是『结束的输入字符』的意思,意思就是,现在上面那条命令回车后,会显示输入字符,而这个输入时输入到档案file2的,按回车就跳到下一行编辑,你的一行内的字符是:55aa,然后按回车,否则永远不会退出这个档案的编辑。
$?:就像一个容器一样,传回执行指令是否正确的结果,它只会记录上一次命令执行的结果,如果上一次执行的结果是正确的话此值就是:0,如果上一次执行结果是错的话就是:非0
例子:
执行命令:cal,肯定是正确的结果,返回0,再次执行:aaa,错误,返回0:。
这两个符号也可以和多条命令结合一起执行,用&& 或者 || 符号分开,但是他们的含义不一样。如下表所示:
注释:cmd1代表一条指令,cmd2代表另一条指令
指令 | 说明 |
cmd1 && cmd2 | 1.如果cmd1执行的结果是正确的,则执行cmd2 2.如果cmd1执行结果是错误的,则不执行cmd2 注释:其实就是判断 cmd1和cmd2与的结果是否正确,如果第一个错了的话,与的结果肯定为错,没必要执行第二个了。 |
cmd1 || cmd2 | 1.如果cmd1执行结果是正确的,则不执行cmd2 2.如果cmd1执行结果是错误的,则执行cmd2 注释:两个数值进行或运算,只要有一个是正确的结果就是正确,如果第一个正确就没有必要去验证后面那个了,原理一样。 |
例子1:
使用命令: cal && echo OK
解释:命令1是正确的,那就执行命令2
例子2:
使用命令:aaaa && echo OK
提示: || 符号的逻辑是一样的。
举例子说明管线的用途:
我们知道在:/etc 下有很多的目录和档案,如果直接使用命令:ls /etc 去查看的话,可能内容会覆盖整个屏幕,导致我们看到的内容不完整,内容还没有办法往前翻看,此时我们就可以使用管线的命令,将数据通过管线传输给less文本查看器,可以使用less阅读器的快捷键等功能就能查看:/etc 下的所有内容啦。
直接使用命令:ls /etc 内容很多,而且不好查看
使用管线的把:/etc 的内容传输到 less 上查看:
使用命令:ls /etc | less
作用:将一段数据根据分析后,根据我们的要求取出我们想要的数据取出不想要的数据。
语法1:cut -d '分隔字符' -f fields
解释:比如有下面的一段字符,我指定分割字符是冒号:":"
/opt/xtensa-lx106-elf/bin:/usr/local/sbin:/usr/local/bin:
/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
上边有8个冒号,那就是分成九段
1 : 2 : 3 : 4:5 : 6: 7 :8 :9
- -f 代表你需要截取的区域
比如像截取第三段也就是:/usr/local/bin
那就应该使用命令:cut -d ':' -f 3
像截取3和8呢?使用命令:cut -d ':' -f 3,8
语法2:cut -c 字符区间
解释:这个命令是对整体的排列信息进行提取的方便我们进行查看。
例子:查看一下所有的环境变量,使用命令:export
可以看到,declare -x 都是一样的,包括空格有12个字符,我不想看这些字符了,怎么做?
使用命令:export | cut -c 12-
解释:把export的内容通过管道传输,然后截取每一行的第12个字符以后的内容.
语法: grep [-acinv] [--color=auto] '搜寻字符串' filename
选项与参数:
选项参数 | 含义 |
-a | 将 binary 档案以 text 档案的方式搜寻数据 |
-c | 计算找到 '搜寻字符串' 的次数 |
-i | 忽略大小写的不同,所以大小写规为相同 |
-n | 输出行号 |
-v | 反向选择,亦即显示出没有 '搜寻字符串' 内容的那一行! |
--color=auto | 可以将找到的关键词部分加上颜色显示 |
例子1:
将ifconfig直接结果的内容档案有:inet6的一行提取出来。
使用命令:ifconfig | grep ' inet6 '
解释:ifconfig执行的结果,通过管道传给grep,然后提取处有,inet6的一行。
例子:
把ifcong的指令执行结果储存于file6档案中,然后再提取里面有inet6的一行。
使用命令:ifconfig | tee file6 | grep 'inet6'
sort可以帮我们的数据进行排序,并根据我们设定的类型进行排序。
语法: sort [-fbMnrtuk] [file or stdin]
选项与参数
选项 | 参数 |
-f | 忽略大小写的差异 |
-b | 忽略前面的空格部分 |
-M | 以月份的名字来排序 |
-n | 使用纯数字进行排序 |
-r | 反向排序 |
-u | 就是uniq,相同的数据,仅出现一个行代表 |
-t | 分隔符,预设使用 tab 进行分割 |
-k | 以指定区间来进行排序 |
例子:
截取passwd以空格作为分隔符,第三部分的数据,可以得到很多的数字:
使用命令:cut -d : -f3 passwd
如何把这些数据进行排序。
使用命令:cut -d: -f3 passwd | sort
加上参数 n ,纯数字排序:
也可以直接指定整个文件的排序,比如说passwd的内容的第三部分进行数字大小的排序。
使用命令:sort -t : -k3 -n passwd
解释:使用命令,对passwd档案,以冒号分割,以第三部分为依据,根据数字的大小进行排序。
含义:想要将重复的资料仅列出一个显示。
语法:
uniq [-ic]
选项
选项 | 含义 |
-i | 忽略大小写字符的不同 |
-c | 进行计数 |
例子:
使用 last 将最近登陆账号列出,仅取出账号栏(第一栏),进行排序后重复的仅仅显示一次
使用命令:last|cut -d ' ' -f1|sort|uniq
如果想显示重复的次数呢,可以使用uniq的 -c 参数
使用命令:last|cut -d ' ' -f1|sort|uniq -c
作用:统计一个档案有多少个字符,多少行,多少字的功能。
语法:
wc [-lwm]
选项:
选项 | 含义 |
-l | 仅列出行 |
-w | 仅列出多少字(英文单词个数) |
-m | 多少字符 |
例子:
查看hosts档案的行数,字数,字符数。
使用命令:wc hosts
输出的三个数字中,分别代表: 『行、字数、字符数』
功能:tr 可以用来删除一段讯息当中的文字,或者是进行文字讯息的替换。
语法:
tr [-ds] SET1 ...
选项:
选项 | 含义 |
-d | 删除信息当中SET1 ...这个字符串 |
-s | 取代掉重复的字符 |
例子1:
把、/etc/hosts 的档案复制到,/test下,然后把hosts档案所有的小写字符转换成大写的
使用命令:tr '[a-z]' '[A-Z]'
等同于命令:cat hosts | tr '[a-z]' '[A-Z]'
解释:把输入文件hosts的所有小写字符全部转换成大写字母,注意此时不会改变hosts的源文件,如果想改变他的源文件怎么做?
注意不能使用:tr '[a-z]' '[A-Z]'
hosts,这样做会损坏源文件。需要分两步走,先执行命令:tr '[a-z]' '[A-Z]' files
输出到一个文件,然后进行剪切命令:mv files hosts
例子:删除指定的字符
可以看到passwd有很多的冒号,那如何删除这些冒号呢?
使用命令:cat passwd | tr -d ':'
功能:他可以用来简单的处理将 [tab] 按键取代成为空格键。
语法:
col [-xb]
选项
选项 | 功能 |
-x | 将 tab 键转换成对等的空格键 |
-b | 在文字内有反斜杠 (/) 时,仅保留反斜杠最后接的那个字符 |
提示:col -x 等同于 expand
例子:
新建一个档案textfile,然后编辑:
利用 cat -A 显示出所有特殊按键,使用命令:cat testfile |cat -A
将tab键转换成空格:使用命令:cat testfile |col -x|cat -A
把两个文件粘贴在一起。
例子:创建两个档案aa,和bb
使用paste把它们粘贴在一起查看:
使用命令:paste aa bb
粘贴aa和 、/etc/hosts
注意:不管paste的两个档案时什么内容,分成两列都给你粘在一起。
作用:他是在处理两个档案之间的数据, 而且,主要是在处理『两个档案当中,有 "相同数据" 的那一行,才将他加在一起』的意思。
语法:
join [-ti12] file1 file2
选项
选项 | 含义 |
-t | join默认以空格符分割数据,并对比第一个字段的数据,如果两个档案相同,则将两笔数据连成一行,且第一个字段放在第一个。 |
-i | 忽略大小写的差异 |
-1 | -1,代表使用第一个档案,代表:第一个档案用哪个字段来分析的意思。例如:-1 4 ,代表使用第一个档案的第4部分来分析 |
-2 | 代表第二个档案要用哪个字段来分析的意思 |
例子1:
创建两个档案aa,bb,内容如下,然后分别使用paste和join把它们放在一起处理。
默认join的粘贴原则如下图所示:
例子2:
把/etc/passwd 的头五行复制到档案,把,/etc/group的头五行复制到dd.然后稍微修改一下cc档案以作区分、
使用paste进行操作,就是把所有内容全部显示出来,然后贴在一起:
在join默认是以空格为分隔符的,在这里我们需要指定分割符是冒号 ":",然后采用第一部分进行比较,第一部分一样的就会结合在一起,而且结合在一起的,如果有重复的就不再显示。
例如:使用join,然后分割符是冒号,以第一部分为比较依据,结果会怎样,如下:
使用命令:join -t ':' cc dd
例子3:
默认都是第一部分进行比较的,那如果想用,不同的部分进行比较如何做?
比如想用冒号为分隔符,使用cc档案的第四部分,和dd档案的第三部分比较。
使用命令:join -t ':' -1 4 aa -2 3 dd
解释:使用冒号为分隔符,使用第1个文件的第4部分aa,和第2个文件的第3部分dd进行比较.
注意:
作用:如果你现在有一个档案的数据很大导致无法复制,你可以把一个档案分割成一小块,然后再进行复制。
语法:
split [-bl] file PREFIX
选项
选项 | 含义 |
-b | 后面可接欲分割成的档案大小,可加单位,例如 b, k, m 等; |
-l | 以行数杢迚行分割。 |
例子:
现在想将/etc/services的档案分割成多个档案怎么做呢?
使用命令:spit -b 3k /etc/services file
解释:把services这个档案分割成多个档案,每个档案的大小是3k,且分割以后档案名的开头是file
那如何把它们结合在一起呢?
使用命令:cat file* > services
提示:同样可以按行进行分割,使用参数 -l 。
8.6.参数代换: xargs
功能:args 则是 arguments (参数)的意思,所以说,这个玩意儿就是在产生某个指令的参数的意思。
例子:
把home这个目录进行打包,然后到另一个目录进行解档
使用命令:tar cvf home.tar /home | tar xvf
注意:没有指定目录就是解档到当前目录
解释如果这样子执行的话home.tar档案是真是存在的
如果不想生成打包文件,不生成 home.tar,然后结果传输给管道,进行传输,怎么做?使用减号 ”-“
使用命令 :tar cvf - /home | tar xvf -
解释:直接把、/home进行打包,通过管道传输,然后解档到当前所在目录下,且不生成打包文件。