3.重定向与管道

发布时间 2023-04-24 10:23:24作者: Mr丶冷文

前言

不知道大家上节课那些命令掌握的怎么样,这些命令一定要自己亲自去敲一遍才能加深印象,不用死记硬背,用的次数多了自然就记住了

本节用到的命令

wc命令

wc命令,全称是word count,并不是你们想的那样,主要用于计算文件的字节数、单词数、或是列数

wc [options] [name...]
参数 含义
-c 字节数
-l 行数
-w 单词数(这里的单词是英文意义上的,以空白隔开)

sort命令

sort命令,顾名思义就是用于排序的命令,主要可针对文本文件的内容,以行为单位来排序

sort [options] name
参数 含义
-b 忽略每行前面开始出的空格字符
-f 忽略大小写
-t split 指定排序时所用的栏位分隔字符,split为分隔字符
-n 依照数值的大小排序
-r 以相反的顺序来排序
-k field1 [fieldN...] 按指定的列进行排序,field为列
-o output 将排序后的结果存入指定的文件,output为文件名

举例说明:

创建一个score.txt文件内容如下,假设是学生的成绩

xiaomi 60
laowang 78
zhangsan 90
Lisi 56
wangwu 89
Zhaoliu 100
tianqi 30

按学生名字顺序输出

sort -f score.txt

按学生成绩倒序输出

sort -nrk2 score.txt

grep命令

为了方便我们后面的演示,这里学一个比较重要的命令grep,它与sedawk被称为Linux文本处理三剑客,后面会详细介绍另外两个

grep命令能够在一个或多个文件中,搜索某一特定的字符模式(也就是正则表达式),此模式可以是单一的字符、字符串、单词或句子

正则表达式:描述一组字符串的一个模式,正则表达式的构成模仿了数学表达式,通过使用操作符将较小的表达式组合成一个新的表达式,这个学过一些编程语言的朋友们应该或多或少都有了解,这里就只做简单说明,如果感兴趣可以看看菜鸟教程里的相关介绍:正则表达式 - 教程

通配符 含义
* 将匹配 0 个(即空白)或多个字符前面出现的字符
. 将匹配任何一个字符,且只能是一个字符
[abc] 匹配方括号中的任意一个字符,括号内为做任意数量的任意字符
[^abc] 匹配除方括号中字符外的所有字符,括号内为做任意数量的任意字符
^ 以后面的字符开头
$ 以前面的字符结尾
grep [options] keyword name... #keyword为正则表达式,name为文件名
参数 含义
-c 仅列出文件中包含keyword的行数
-i 忽略模式中的字母大小写
-l 列出带有匹配行的文件名
-n 在每一行的最前面列出行号
-v 列出没有匹配模式的行
-r 递归查找

我们以/etc/passwd文件为例对该命令做一个简单的认识

例1:查找文件中包含me的行

grep 'me' /etc/passwd

例2:在上述的的基础上输出行号

grep -n 'me' /etc/passwd

例3:列出共有多少行以s开头n结尾的行数

grep -c '^s.*n$' /etc/passwd

例4:列出/etc目录下以s开头n结尾的文件及行号,并忽略错误输出

grep -nr '^s.*n$' /etc/* 2>/dev/null

重定向

基本概念介绍

Liunx shell中,重定向为意思为改变标准输入输出的方向,重定向分为两种,输入重定向和输出重定向,这么说可能有些抽象,先看一些概念

  • 什么是输入输出方向

    • 输入方向:数据从哪里流向程序
    • 输出方向:数据从程序流向哪里
  • 什么是标准的输入入输出方向

    • 标准输入方向:数据默认的输入方向为从键盘流向程序
    • 标准输出方向:数据默认的输出方向为从程序流向显示器
  • 什么是输入输出重定向

    • 输入重定向:改变了数据的标准输入方向,即数据从其它地方流入程序
    • 输出重定向:改变了数据的标准输出方向,即数据从程序流入其它地方

看完这些概念大家是不是已经蒙了,这个没关系,后面会有例子帮大家理清这些的

文件描述符

在Linux中,一切皆文件,包括标准输入设备(键盘)和标准输出设备(显示器)在内的所有计算机硬件都是文件,为了区分这些打开的文件,Linux会为每个文件有一个整数做标识,这个整数就被称为文件描述符(File Descriptor),相当于一个非负的文件索引,我们可以通过文件描述符操作相应的文件

在LLinux进程中,会默认打开三个文件描述符

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

一般来说,我们打开文件后占用一个文件描述符,由于0、1、2已被标准文件描述符占用,他就可以往后找一个没有被占用的文件描述符来占用

大家知道有这么个东西就行了,这个用的不多,就知道我上面例出的三个的意思就行,如果大家想要深入了解这块内容,大家可以看看CSDN上的这篇帖子彻底弄懂 Linux 下的文件描述符(fd)

输出重定向

输出重定向是指命令的结果不再输出到显示器上,而是输出到如文件中。这样做的最大好处就是把程序的输出结果保存起来,当我们需要的时候可以随时查询

在Linux中有如下的输出重定向符号

命令 说明
command >file 以覆盖的方式,把 command 的正确输出结果输出到 file 文件中
command >>file 以追加的方式,把 command 的正确输出结果输出到 file 文件中
command n>file 以覆盖的方式,把文件描述符为 n 的文件重定向到 file文件中
command n>>file 以追加的方式,把文件描述符为 n 的文件重定向到 file文件中
command >file n>&m 以覆盖的方式,把文件描述符为n与文件描述符为m的输出合并到file文件中

当描述符为1时可以不写,默认就是1

例1:标准输出

把/etc下的文件详情输出到桌面的demo1.txt中

ls -l /etc 1> ~/Desktop/demo1.txt
ls -l /etc > ~/Desktop/demo1.txt

例2:错误输出

把错误输出重定向到桌面的err.txt中

命令正确执行是没有错误信息的,我们必须刻意地让命令执行出错

ls abcd.aaa 2>err.txt

例3:综合练习

执行下面的程序完成相关操作

在桌面创建名为output.sh的文件,内容如下:

#!/bin/bash
while :
do
	username=`cat /proc/sys/kernel/random/uuid | md5sum |cut -c 1-9`
	path=`cat /proc/sys/kernel/random/uuid | md5sum |cut -c 1-9`
	echo `date` "user [$username] view file: $path"
	ls $path
	sleep 1
done

在桌面执行如下命令:

chmod +x output.sh

运行文件可以查看效果

将正常输出保留在屏幕,错误输出到桌面的err.log的文件中

./output.sh 2>err.log

将错误输出保留在屏幕,正常输出到out.log的文件中

./output.sh 1>out.log

将错误输出到err.log文件中,正常输出到out.log的文件中

./output.sh 1>out.log 2>err.log

将错误输出与正常输出合并输出到application.log文件中

./output.sh >application.log 2>&1 # 把标准输出重定向到application.log的文件中,然后把错误输出合并到标准输出中

/dev/null 文件

上节课我们讲过,/dev目录是存在设备的特殊目录,这个目录下有个null设备,即为一个空白设备,有时我们不想把信息输出到屏幕,也不想输出到文件,就可以重定向到此,断续以上面的程序举例

./output.sh >/dev/null 2>&1

输入重定向

与输出重定向类似,输入重定向是改变输入的方向,不再使用键盘作为命令输入的来源,而是使用文件

在Linux中有如下的输入重定向符号

命令 说明
command <file 将 file 文件中的内容作为 command 的输入
command <<END 从标准输入(键盘)中读取数据,直到遇见分界符 END 才停止(分界符可以是任意的字符串,用户自己定义,常见的有EOF:end of file)

例1:统计标准输入的信息

我们可以把标准输入作为wc命令的输入来计统计我们从键盘字符的信息

wc <<EOF
123456
hello world
i amd lengwen
kevinlu98.cn
EOF

例2:将用户的输入输出到文件

我们希望将我们的输入直接输出到文件中,这样可以方便快捷的创建文件

cat <<EOF>file.txt
hello
i amd lengwen
my site is kevinlu98.cn
EOF

管道

Linux除了有上面的输入输出重定向,还有一种功能,就是可以将两个或者多个命令(程序或者进程)连接到一起,把一个命令的输出作为下一个命令的输入,以这种方式连接的两个或者多个命令就形成了管道(pipeline)

Linux 管道使用竖线|连接多个命令,这被称为管道符

command1 | command2
command1 | command2 [|commandN...]

当在两个命令之间设置管道时,管道符|左边命令的输出就变成了右边命令的输入。只要第一个命令向标准输出写入,而第二个命令是从标准输入读取,那么这两个命令就可以形成一个管道,这里需要注意,command2 必须可以处理 command1 的输出结果

管道也是一种文件,管道中的读数据是一次性操作,数据一旦被读,它就从管道中被抛弃

例1:查找文件是否在目录内

查找passwd是否在/etc目录下

ls /etc/ | grep 'passwd'

列出当前目录下.bashrc的详细信息

ls -a | grep 'passwd'

例2:按文件大小顺序输出

我们先列出文件的详细信息,文件的大小在第5列,然后用数值方式对其逆向输出

ls -l | sort -nrk5

小结

这节课我们主要讲了重定向及管道,这两个都是改变文件的输出,不同的是重定向是连接命令的输出与文件,而管道是连接命令与命令的,这两个知识点在日常工作中用到的频率还是非常高的,希望大家可以好好理解一下,自己多动手写一写,想一些需求自己做一做