前面文章我们学习了 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
- [root@heimatengyun test]# env
- XDG_SESSION_ID=2
- HOSTNAME=heimatengyun
- SELINUX_ROLE_REQUESTED=
- TERM=Linux
- SHELL=/bin/bash
- [root@heimatengyun test]# echo $SHELL
- /bin/bash
- [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@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
- [root@heimatengyun ~]# su test
- [test@heimatengyun root]$ echo $MYDIR
- [test@heimatengyun root]$ exit
- exit
- [root@heimatengyun ~]# export MYDIR
- [root@heimatengyun ~]# env
- XDG_SESSION_ID=2
- HOSTNAME=heimatengyun
- SELINUX_USE_CURRENT_RANGE=
- MYDIR=/etc/profile.d/
- [root@heimatengyun ~]# su test
- [test@heimatengyun root]$ echo $MYDIR
- /etc/profile.d/
- [test@heimatengyun root]$ exit
- exit
来源: https://www.cnblogs.com/heimatengyun/p/12206321.html