前面文章我们学习了linux基础命令,如果将不同命令组合使用则可以成倍提高工作效率。本文将学习重定向、管道符、通配符、转义符、以及重要的环境变量相关知识,为后面的shell编程打下基础。

一、IO重定向

前文我们已经讲解了近60个linux常用命令,前文讲解的查看当前目录下有哪些文件的ls命令

[root@heimatengyun test]# ls
test1.txt test2.txt

执行命令后默认结果是输出到电脑屏幕(显示器)上的,但是如果我们想让命令执行结果保存到文件中,方便以后需要的时候可以随时查阅,我们该怎么做呢?这就要用到重定向的知识。

1.1 重定向概述

Linux shell重定向是指修改系统命令的默认执行方式,我们可以理解为“改变输入和输出的方向”,分为输入重定向和输出重定向。

既然重定向是改变默认的输入输出方向,那默认的输入输出方向又是什么呢?

相对程序而已,从键盘读取用户输入数据供程序使用,也就是数据流从键盘到程序,这就是标准的输入;程序运算产生的结果数据直接呈现在显示器上,也就是数据流从程序到显示器,这就是标准的输出。默认的标准输入、输出如下图:

将默认的从键盘读取数据改为从文件读取数据,也就是数据流从文件到程序,就是输入重定向;程序运算产生的结果数据不显示在显示器上而是改为输入到文件,也就是数据流从程序到文件,就是输出重定向

计算机的硬件设备有很多,常见的输入设备有键盘、鼠标、麦克风、手写板等,输出设备有显示器、投影仪、打印机等。 不过,在Linux中,标准输入设备一般指键盘,标准输出设备一般指显示器。

前文提到过,Linux中一切皆文件,包括键盘、显示器等输入输出设备在内的所有计算机硬件都是文件。为了表示和区分已经打开的文件,Linux会为每个文件分配一个ID,这个ID是一个整数,被称为文件描述符(File Descriptor)。

与输入输出有关的文件描述符如下表:

文件描述符 文件名 类型 硬件
0 stdin 标准输入文件 硬盘
1 stdout 标准输出文件 显示器
2 stderr 标准错误输出文件 显示器

Linux程序在执行任何形式的IO操作时,都是在读取或写入一个文件描述符。一个文件描述符只是一个和打开的文件相关联的整数,它被扣可能是一个硬盘上的普通文件、FIFO、管道、终端、键盘、显示器,甚至是一个网络连接。stdin、stdout、stderr默认都是打开的,在重定向的过程中,0、1、2这三个文件描述符可以直接使用。

1.2 重定向分类

重定向分为输入和输出重定向。简言之,输入重定向就是把文件导入到命令,输出重定向则是把原本要输出到屏幕的信息写入到指定文件中。平时工作中,相对于输入重定向,输出重定向使用频率更高,因此又将输出重定向细分为标准输出重定向和错误输出重定向,输出重定向又分为:清空写入和追加两种模式。

关于标准输出和错误输出请看下面示例:

[root@heimatengyun ~]# ls test/
test1.txt test2.txt
[root@heimatengyun ~]# ls xxx
ls: cannot access xxx: No such file or directory

用ls命令查看制定目录下的文件信息,如果文件夹存在且文件夹下有内容将输出文件所有者、所属组、文件大小等信息,也就是ls命令的标准输出信息。但是如果查看一个不存在的文件夹,则提示文件不存在的报错信息,也就是ls命令的错误输出信息。如果要把上边原本输出到屏幕的信息直接写入到文件中而不是显示到屏幕,就要区别对待这两种输出信息。

1.2.1 输入重定向

输入重定向相关的符号和作用如下表

符号 作用
命令 < 文件 将文件作为命令的标准输入
命令 << 分界符 从标准输入中读入,直到遇到分解符才停止
命令 < 文件1 > 文件2 将文件1作为命令的标准输入并将标准输出到文件2

输入重定向相对来说用的很少,输入重定向的作用是将文件直接导入到命令中。/etc/passwd文件存储了系统用户信息,一行记录一个用户。以下示例演示通过输入重定向将此文件导入到wc命令,统计用户个数。

[root@heimatengyun test]# wc -l < /etc/passwd
39
1.2.2 输出重定向

输出重定向用到的符号和作用如下表

符号 作用
命令 1> 文件 将标准输出重定向到文件中(清空原有文件数据),1可以省略
命令 2> 文件 将错误输出重定向到文件中(清空原有文件数据)
命令 1>> 文件 将标准输出重定向到文件中(追加到原有内容后面),1可以省略
命令 2>> 文件 将错误输出重定向到文件中(追加到原有内容后面)
命令 &>> 文件 将标准输出和错误输出共同写入到文件中(追加到原有内容后面)
命令 >> 文件 2>&1 同上条命令:命令 &>> 文件

对于重定向中的标准输出模式,一般省略文件描述符1不写,而错误输出模式的文件描述符2是必须要写的。

1.2.3 输出重定向案例

通过man命令查看ls命令的使用方法,并将输出信息重定向到ls.txt文件中,然后就可以使用cat命令查看ls.txt文件的信息。

[root@heimatengyun test]# ls
test1.txt test2.txt
[root@heimatengyun test]# man ls > ls.txt
[root@heimatengyun test]# ls
ls.txt test1.txt test2.txt
[root@heimatengyun test]# cat ls.txt
LS(1) User Commands LS(1)
NAME
ls - list directory contents
SYNOPSIS
ls [OPTION]... [FILE]...
DESCRIPTION
...省略部分内容

接下来我们演示清空写入和追加写入的区别,先通过覆盖写入模式向ls.txt文件(原本有ls的帮助信息内容)写入一行数据,查看内容变化,然后再通过追加写入模式向文件写入一次数据,再查看文件内容的变化

[root@heimatengyun test]# echo "wellcome" > ls.txt
[root@heimatengyun test]# cat ls.txt
wellcome
[root@heimatengyun test]# echo "write message again" >> ls.txt
[root@heimatengyun test]# cat ls.txt
wellcome
write message again

可以看到覆盖模式将清空文件原有内容,追加模式则在原有内容后面添加数据。

1.2.4 标准输出和错误输出区别

虽然都是重定向技术,不同命令的标准输出和错误输出还是有区别的。如果一个命令执行成功,通过标准输出到文件是没有问题的,但是如果要错误输出重定向到文件是不会成功的,依旧会显示信息到屏幕。反之,如果一个命令执行失败,通过错误输出到文件是没有问题的,但是如果要输出到标准输出是不会成功的,依旧会显示到屏幕。

通过ls命令查看一个已经存在的文件,并将信息重定向到ls.txt文件,查看该文件可以看到成功存入信息。将其错误输出重定向到ls-err.txt文件,由于查看的该文件存在,没有错误信息所以看到查询成功的文件信息依然显示在了屏幕上,而错误重定向的文件里没有内容。

[root@heimatengyun test]# ls
test1.txt test2.txt
[root@heimatengyun test]# ls -l test1.txt
-rw-r--r--. 1 root root 0 Nov 30 15:34 test1.txt
[root@heimatengyun test]# ls -l test1.txt > ls.txt
[root@heimatengyun test]# ls
ls.txt test1.txt test2.txt
[root@heimatengyun test]# cat ls.txt
-rw-r--r--. 1 root root 0 Nov 30 15:34 test1.txt
[root@heimatengyun test]# ls -l test1.txt 2> ls-err.txt
-rw-r--r--. 1 root root 0 Nov 30 15:34 test1.txt
[root@heimatengyun test]# ls
ls-err.txt ls.txt test1.txt test2.txt
[root@heimatengyun test]# cat ls-err.txt

二、管道符

通过管道符可以把很多命令组合起来,提高工作效率。简言之管道符的作用就是:把前一个命令原本要输出到屏幕的标准正常数据当作后一个命令的标准输入。

管道符用|表示,使用格式为:命令A|命令B|命令C...

  • 案例1:统计被禁止登陆系统的用户数
[root@heimatengyun test]# grep "/sbin/nologin" /etc/passwd |wc -l
34

通过“linux入门系列5--新手必会的linux命令”介绍的grep命令匹配/etc/passwd文件中的关键字“/sbin/nologin”查找出被限制登陆系统的用户,并将匹配结果输入到wc命令,统计匹配到的行数,即为被限制登陆系统的用户数。

  • 案例2:将文件内容中的小写字母替换为大写字母输出
[root@heimatengyun test]# cat test1.txt
wellcome
[root@heimatengyun test]# cat test1.txt |tr [a-z] [A-Z]
WELLCOME
[root@heimatengyun test]# cat test1.txt
wellcome

通过cat命令读取test1.txt文件内容并导入到tr命令,通过tr命令将内容中的小写字母替换为大写字母。可以看到只是对读取后的内容进行替换,对原文件没有影响。

tr命令作用是替换文本文件中的字符,格式为:tr [原始字符] [目标字符]

很多时候想要快速地替换文本中的一些词汇,如果手工替换,难免工作量巨大,尤其是需要处理大批量内容的时候。这时tr命令就可以派上用场,通过管道符将文本内容传递给它进行替换操作即可。

ps:前文讲了近60个Linux命令,命令太多不可能一一涵盖,其余的命令将根据场景需求逐步以案例的形式分散到各文中进行演示。

三、通配符

通配符的概念在很多语言中都存在,比如java、c#等,其作用就是模糊匹配。

假设你在电脑上存放了很多小电影,某一天突然想看某位老师的电影作品,但是由于文件太多以至于记不清楚电影文件的名称了,只是依稀记得文件名包含了几个关键字,这时候你怎么快速找到对应的文件呢?

通配符就是面对这种场景而生,熟练使用通配符,再多电影都不迷路。通配符顾名思义就是通用的匹配信息的符号,主要包含以下几个:

符号 意义
* 匹配0个和多个字符
匹配单个字符
[0-9] 匹配0~9之间的单个数字字符
[123] 匹配1、2、3这三个指定数字中的任意一个数字
[abc] 匹配a、b、c三个字符中的任意一个字符
  • 案例1:匹配文件名以test开头的所有文件
[root@heimatengyun test]# ls
test1.txt test2.txt
[root@heimatengyun test]# ls -l test*
-rw-r--r--. 1 root root 9 Nov 30 20:43 test1.txt
-rw-r--r--. 1 root root 0 Nov 30 15:34 test2.txt
  • 案例2:匹配文件名最后一位为1或3的所有文件
[root@heimatengyun test]# ls
test1.txt test2.txt
[root@heimatengyun test]# ls -l test[13].txt
-rw-r--r--. 1 root root 9 Nov 30 20:43 test1.txt

四、转义符

“linux入门系列5--新手必会的linux命令”提到,人和Linux内核之间的交互是通过在shell终端中执行相关命令来实现的,为了能更好地理解用户的表达,除了通配符、管道符,shell解释器还提供了特别丰富的转义字符来处理用户输入的特殊数据。

本文只抽取几个常用的通配符进行讲解,转义符及对应的功能如下:

转义符 作用
\ 反斜杠,使后边的一个变量变为单纯的字符串
'' 单引号,转义其中所有的变量为单纯的字符串
"" 双引号,保留其中的变量属性,不进行转义处理
`` 反引号,把其中的命令执行后返回结果
  • 案例1:输出美元$表示的价格
[root@heimatengyun test]# PRICE=99
[root@heimatengyun test]# echo "the price is $PRICE"
the price is 99
[root@heimatengyun test]# echo "the price is $$PRICE"
the price is 12395PRICE

定义PRICE变量保存价格,然后通过echo命令输出,发现输出的不是预期结果。原因是Linux中$表示变量,$$则有特殊的作用,表示当前程序的进程ID号。这时就需要反斜杠来进行转义,去除其特殊功能,将这个提取符转义为单纯的文本。

[root@heimatengyun test]# echo "the price is \$$PRICE"
the price is $99
  • 案例2:将命令执行结果值赋值给变量并输出
[root@heimatengyun test]# uname -a
Linux heimatengyun 3.10.0-123.el7.x86_64 #1 SMP Mon Jun 30 12:09:22 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux
[root@heimatengyun test]# MYSYS=`uname -a`
[root@heimatengyun test]# echo $MYSYS
Linux heimatengyun 3.10.0-123.el7.x86_64 #1 SMP Mon Jun 30 12:09:22 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux

用uname命令查看当前操作系统信息,并赋值给变量MYSYS,然后输出变量值。更多变量相关知识将在下一篇文章中详细介绍,此处主要掌握反引号这个转义符。

五、环境变量

变量是计算机系统用于保存可变值的数据类型,在Linux系统中,变量名称一般是大写的,这是一种约定俗成的规范。直接通过变量名即可获得对应的变量值。

环境变量是一种特殊的变量,是操作系统要正常运行的前提,数百个环境变量协同工作才使得操作系统能正常为用户提供服务。然而我们没有必要去全部学习和掌握所有数百个环境变量,只需要学习一部分常用的即可。

5.1 查看环境变量之env命令

一般通过env命令查看环境变量名

[root@heimatengyun test]# env
XDG_SESSION_ID=2
HOSTNAME=heimatengyun
SELINUX_ROLE_REQUESTED=
TERM=linux
SHELL=/bin/bash
...省略部分内容

用echo命令查询环境变量值

[root@heimatengyun test]# echo $SHELL
/bin/bash

Linux作为一个多用户多任务操作系统,能够为每个用户提供独立的工作环境,因此,一个相同的变量会因为用户身份的不同而具有不同的值

案例:使用不同用户查看HOME环境变量的值

[root@heimatengyun ~]# echo $HOME
/root
[root@heimatengyun ~]# su - test
Last login: Sat Nov 30 22:39:50 CST 2019 on pts/0
[test@heimatengyun ~]$ echo $HOME
/home/test
[test@heimatengyun ~]$ exit
logout
[root@heimatengyun ~]#

案例中先使用root用户查看$HOME的值,然后切换到test用户再次查看$HOME,从试验结果上看相同环境变量值却是不一样的。

注意:关于用户切换命令su的用法,su test和su - test是有非常大区别的,如果不加-表示只是切换用户不切换shell环境,如果加上-则表示连同shell环境一起替换,此处无论是否切换shell环境,两个不同用户的$HOME值都不一样。

5.2 设置环境变量之export命令

变量是由固定的变量名与用户或系统设置的变量值两部分注册,因此我们完全可以根据工作需要自行创建变量。

以下案例演示创建一个名称为$MYDIR,值为/etc/profile.d/ 目录的自定义变量,这样我们只需要通过该变量,就可以很方便的进入到值对应的目录。

[root@heimatengyun test]# MYDIR=/etc/profile.d/
[root@heimatengyun test]# echo $MYDIR
/etc/profile.d/
[root@heimatengyun test]# pwd
/root/test
[root@heimatengyun test]# cd $MYDIR
[root@heimatengyun profile.d]# pwd
/etc/profile.d

此时创建的变量$MYDIR不具有全局性,作用范围有限,默认情况下不能被其他用户使用。

[root@heimatengyun ~]# su test
[test@heimatengyun root]$ echo $MYDIR [test@heimatengyun root]$ exit
exit

可以看到切换到test用户后,该变量没有值,并且通过env命令查看也未查到该变量。

如果要想让其他用户也可以使用该变量,则需要用export命令,将其提升为全局变量。注意export命令后的变量名不加$。

[root@heimatengyun ~]# export MYDIR
[root@heimatengyun ~]# env
XDG_SESSION_ID=2
HOSTNAME=heimatengyun
SELINUX_USE_CURRENT_RANGE=
MYDIR=/etc/profile.d/
...省略部分内容

通过env命令也可以查到该变量,此时我们在切换到test用户查看是否可以使用

[root@heimatengyun ~]# su test
[test@heimatengyun root]$ echo $MYDIR
/etc/profile.d/
[test@heimatengyun root]$ exit
exit

注意:再次强调一下,su test和su - test是有非常大区别的,如果不加-表示只是切换用户不切换shell环境。本例只是切换用户到test并没切换环境所以可以使用$MYDIR,如果使用su - test 把shell环境也替换的话,将无法使用自定义的$MYDIR环境变量。

5.3 常用的环境变量

下表列举几个重要常用的环境变量

变量名称 作用
HOME 用户家目录
SHELL 用户在使用的shell解释器名称
HISTSIZE 输出的历史命令记录条数
HISTFILESIZE 保存的历史命令记录条数
LANG 系统语言、语系名称
PATH 定义解释器搜索用户执行命令的路径

5.4 命令执行流程

Linux系统中一切皆文件,Linux命令也不例外。当用户执行一条命令之后,Linux系统到底发生了什么事情呢?

简单来说,命令在Linux中的执行分为以下4个步骤

(1)判断用户是否以绝对路径或相对路径的方式输入命令,如果是则直接执行,不是则进行第二步

(2)检查用户输入的命令是否有别名命令,如果有别名找到原命令,如果无则进行第三步

(3)bash解释器判断用户输入的是内部命令还是外部命令,如是内部命令则直接执行,外部命令则进行第四步

(4)系统在PATH环境变量中查找用户输入的命令,找到文件后执行命令。

简单理解就是用户通过shell输入命令,shell解释器查找对应的命令文件并执行命令

注意:思考一下一个经典的问题,能否将当前目录(.)添加到环境变量PATH中呢?

尽管可以将当前目录(.)添加到PATH变量中,使得在某些情况下可以让用户免去输入命令路径的麻烦,但是,这样存在很大的安全风险。假如黑客在常用的公用目录/tmp下存放一个与ls或cd等命令同名的病毒文件,而用户恰巧又在公共目录中执行了这些命令,那就很可能中招了。

了解linux命令执行流程后,当接手一台Linux系统后,在执行命令前先检查PATH变量中是否有可以的目录,这是一个很好的习惯。

至此,已经学习了大部分Linux命令,知识积累的差不多了,下一篇文章我们将综合前面学到的知识,正式进入shell编程。

linux入门系列7--管道符、重定向、环境变量的更多相关文章

  1. linux入门系列8--shell编程

    本文将结合前面介绍的Linux命令.管道符等知识,通过VI编辑器编写Shell脚本,实现能自动化工作的脚本文件. 在讲解Linux常用命令"linux入门系列5--新手必会的linux命令& ...

  2. linux入门系列16--文件共享之Samba和NFS

    前一篇文章"linux入门系列15--文件传输之vsftp服务"讲解了文件传输,本篇继续讲解文件共享相关知识. 文件共享在生活和工作中非常常见,比如同一团队中不同成员需要共同维护同 ...

  3. linux入门系列18--Web服务之Apache服务2

    接上一篇文章,在了解Apache基本配置以及SELinux相关知识后,继续演示Apache提供的虚拟主机功能以及访问控制方式. 如果还没看上一篇的建议先查看后再来,上篇文章"linux入门系 ...

  4. linux入门系列2--CentOs图形界面操作及目录结构

    上一篇文章"linux入门系列1--环境准备及linux安装"直观演示了虚拟机软件VMware和Centos操作系统的安装,按照文章一步一步操作,一定都可以安装成功.装好系统之后, ...

  5. linux入门系列4--vi/vim编辑器

    上一篇文章"linux入门系列3--linux远程登陆工具"讲解了如何使用常用的工具远程连接和管理linux服务器,要管理服务器必然会涉及到脚本文件的创建.编辑工作,因此在介绍命令 ...

  6. linux入门系列5--新手必会的linux命令

    上一篇文章"linux入门系列4--vi/vim编辑器"我们讨论了在linux下如何快速高效对文本文件进行编辑和管理,本文将进一步学习必须掌握的linux命令,掌握这些命令才能让计 ...

  7. linux入门系列12--磁盘管理之分区、格式化与挂载

    前面系列文章讲解了VI编辑器.常用命令.防火墙及网络服务管理,本篇将讲解磁盘管理相关知识. 本文将会介绍大量的Linux命令,其中有一部分在"linux入门系列5--新手必会的linux命令 ...

  8. linux入门系列13--磁盘管理之RAID、LVM技术

    前一篇文章学习了磁盘分区.格式化.挂载等相关知识,本文将讲解RAID和LVM技术. 磁盘管理操作主要是运维人员用的较多,如果只是单纯的开发人员,可以先略过本文.但是在很多小公司里往往都是一人多用,运维 ...

  9. linux入门系列14--ssh服务及主机远程管理

    通过前面十余篇文章的介绍,相信已经初步入门Linux本地管理的基本方法了,后续的文章将介绍Linux中常用的服务部署以及如何为外部提供相应的服务. 系列文章第三篇"linux入门系列3--l ...

随机推荐

  1. Python--day62--删除出版社

    删除成出版社关键代码:

  2. java 合并流(SequenceInputStream)

    需要两个源文件,还有输出的目标文件 SequenceInputStream: 将两个文件的内容合并成一个文件 该类提供的方法: SequenceInputStream(InputStream s1, ...

  3. linux 使用 /proc 文件系统

    /proc 文件系统是一个特殊的软件创建的文件系统, 内核用来输出消息到外界. /proc 下 的每个文件都绑到一个内核函数上, 当文件被读的时候即时产生文件内容. 我们已经见到 一些这样的文件起作用 ...

  4. linux进程互斥等待

    我们已经见到当一个进程调用 wake_up 在等待队列上, 所有的在这个队列上等待的进程 被置为可运行的. 在许多情况下, 这是正确的做法. 但是, 在别的情况下, 可能提前知道 只有一个被唤醒的进程 ...

  5. jquery的offset().top和js的offsetTop的区别,以及jquery的offset().top的实现方法

    jquery的offset().top和js的offsetTop的区别,以及jquery的offset().top的实现方法 offset().top是JQ的方法,需要引入JQ才能使用,它获取的是你绑 ...

  6. Linux 内核端点

    USB 通讯的最基本形式是通过某些称为 端点 的. 一个 USB 端点只能在一个方向承载数 据, 或者从主机到设备(称为输出端点)或者从设备到主机(称为输入端点). 端点可看作一 个单向的管道. 一个 ...

  7. promise 讲解

    Promise的出现  解决了 js 回调地狱得问题 回调地狱图 Promise解决回调地狱 是不是美观多了.. 实例化Promise时传入方法里的两个参数 resolve(成功的回调)和reject ...

  8. Nutch2.3 编译和安装配置

    Nutch2.3 编译和安装配置 [一].介绍 Nutch 是一个开源Java 实现的搜索引擎.它提供了我们运行自己的搜索引擎所需的全部工具.包括全文搜索和Web爬虫.现在Nutch分为两个版本:1. ...

  9. Linux网络IO模型

    同步和异步,阻塞和非阻塞 同步和异步 关注的是结果消息的通信机制 同步:同步的意思就是调用方需要主动等待结果的返回 异步:异步的意思就是不需要主动等待结果的返回,而是通过其他手段比如,状态通知,回调函 ...

  10. Struts2 类型转换(易百教程)

    在HTTP请求中的一切都被视为一个String由协议.这包括数字,布尔值,整数,日期,小数和一切.每一件事情是一个字符串,将根据HTTP.然而,Struts类可以有任何数据类型的属性.Struts的自 ...