数据的处理

理解Linux输入和输出

Linux中将每个对象都看作文件来处理,包括输入和输出过程,其用文件描述符来标识每个文件对象。文件描述符是一个非负整数,每个过程中一次最多可以有9个文件描述符。bash shell保留了3个文件描述符如下:

文件描述符

缩 写

描 述

0

STDIN

标准输入

1

STDOUT

标准输出

2

STDERR

标准错误

说明:

STDIN的默认设备是键盘,STDOUTSTDERR的默认设备是显示器。重定向输出时,有3种情况:

仅重定向错误或输出,此时将文件描述符紧挨着放到重定向符号前边,中间不能有空格:

重定向错误和输出到不同的文件中,此时使用两个重定向符号:

重定向错误和输出到同一文件中,使用特殊的重定向符号:

对脚本中的数据进行重定向

临时重定向输出

想在脚本中重定向自定义的错误消息到STDERR中,如下操作:
echo “This is an error message” >&2
在运行包含该行语句的脚本时,消息输出到STDERR指向的任何位置中。

永久重定向输出

如果脚本中包含大量需要重定向的输出信息,可以使用exec命令告诉shell执行脚本期间将某个文件描述符重定向到固定的位置:

#! /bin/bash
# redirecting output to different locations

exec 2> testerror

exec 1> testop

echo "This section should go to the testop file"
echo "but this should go to the testerror file" >&2

重定向输入

exec 0< inputfile

自定义的重定向

shell中的9个文件描述符之前介绍了3个,其余6个当作输入或者输出均可。

重定向为输出文件描述符:

exec 3> outfile

echo "This should display on the monitor"
echo "This should be stored in the outfile" >&3

但是如何从已重定向的文件描述符中进行恢复呢?其实很简单,只需要重定向回STDOUT中即可:

exec 3>&1

echo "This should display on the monitor"
echo "This should be stored in the outfile" >&3

重定向为输入文件描述符:

exec 6<&0
exec 0<output.txt

count=1
while read line
do
        echo "Line $count: $line"
        count=$[ $count + 1 ]
done


exec 0<&6
read -p "Are you done now? " answer

case $answer in
Y | y)
        echo "Goodbye";;
N | n)
        echo "Sorry. This is the end";;
esac

重定向为输入输出文件描述符:

将一个文件描述符同时重定向为具有输入和输出功能时,由于shell维护一个内部指针,指向当前文件中的位置,任何读写操作都是从上次保存的文件指针处开始的,此时必须小心处理,否则会产生覆盖现象,如下所示:

exec 3<> output.txt
read line <&3
echo "Read: $line"
echo "This is a test line" >&3

说明:

read命令读取第一行数据后,文件指针移动到第二行开始,因此执行写操作时会覆盖文件output.txt中的第二行数据。

关闭文件描述符:

如果自定义了新的输入或者输出文件描述符,shell会在脚本退出时自动关闭它们。但是如果想在脚本结束之前手动关闭文件描述符,需要将其重定向到特殊符号&-,如下所示:
exec 3>&-,该语句关闭文件描述符3,从而阻止在脚本中再次使用它。如果不小心再次使用了该文件描述符,那么会得到bad file descriptor错误提示。

列出打开的文件描述符

9个文件描述符中,很难记住哪个文件描述符被重定向到哪,bash shell提供了lsof命令。lsof命令列出了整个Linux系统中打开的所有文件描述符。由于该命令向非系统管理员提供了Linux相关的信息,因此,很多Linux系统隐藏了该功能,在centos中,通过which lsof,可以得到其被存放在/usr/sbin/lsof中,以全路径运行该命令,会产生大量的输出。可以使用-p指定具体的PID,也可以使用-d来指定具体的文件描述符,-a选项对任何两个选项执行布尔AND运算。要想知道当前进程的PID,可以使用环境变量"$$"

lsof命令结果描述:

COMMAND

正在运行的命令名的前9个字符

PID

进程ID

USER

进程属主的登录名

FD

文件描述符[r表示可读,w表示可写,u表示可读写]

TYPE

文件类型[CHR表示字符型,BLK表示块型,DIR表示目录,REG表示常规文件]

DEVICE

设备号[主设备号和从设备号]

SIZE

文件大小

NODE

本地文件节点数

NAME

文件名

我们知道0,1,2分别表示STDINSTDOUTSTDERR,从上边运行结果可知这三个文件描述符关联的文件类型都是字符型,都指向终端,所以输出文件名都是终端的设备名。这三种标准文件都支持读和写,虽然我们一般不用STDIN来写数据,也不用STDOUT来读数据,这样看起来就太奇怪了。

阻止命令输出

可以将STDERR重定义到一个称为null的特殊文件,Linux中,null文件的位置是/dev/null,任何重定向到该位置的文件都会被丢弃而不进行显示。当然,也可以将/dev/null作为输入文件,这样由于/dev/null文件中不包含任何内容,其作用是可以快速删除现有文件中的数据而不用删除文件本身:

这是清除日志文件的一个通用方法,既可以清除文件内容,又可以保留文件存在。

创建临时文件

Linux使用/tmp目录来存放临时文件,多数Linux系统在启动时会自动删除/tmp目录中的文件。系统中的任何用户都有权限对/tmp目录进行读和写。

mktemp命令用于在当前目录中创建临时文件。默认情况下,使用mktemp命令时只需要指定一个文件名模板就可以了。模板可以包含任意文本,在文件名末尾加上6X就可以了,如下:

mktemp命令使用6个字符代替6X,从而确保文件名在本地目录中的唯一性。

如果在使用mktemp命令时加上-t选项,那么该命令会在/tmp目录下创建临时文件,并返回临时文件的全路径名,如下所示:

mktemp加上-d选项表示在当前目录下创建临时目录。

  

记录消息

如果需要想输出发送到显示器的同时又记录到日志文件中,一种方式是使用两次重定向,另一种方式时使用tee命令。tee命令相当于管道的一个T型接口,其将STDIN接受过来的数据同时发送给两个目的地:一个是STDOUT,另一个是tee指定的文件名:tee filename

如果使用tee命令时加上了-a选项,表示在testfile文件中追加数据而不是覆盖,如下所示:

原文地址:https://www.cnblogs.com/benxintuzi/p/4710422.html