第二十七课 LinuxShell编程五之呈现数据

说明:本文部分内容均摘取自书籍《Linux命令行与shell脚本编程大全》,版权归原作者所有。《Linux命令行与shell脚本编程大全》(第三版)第十五章学习总结

第十五章:呈现数据

本章内容

再探重定向
标准输入和输出
报告错误
丢弃错误
丢弃数据
创建日志文件

15.1 理解输入和输出

两种显示脚本输出的方法

在显示器屏幕上显示输出
将输出重定向到文件中

15.1.1 标准文件描述符

Linux系统将每个对象当做文件处理,这包括输入和输出进程
Linux用文件描述符(file descriptor)来标识每个文件对象
文件描述符是一个非负整数,可以唯一标识回话中打开的文件
每个进程一次最多可以有九个文件描述符
出于特殊目的,bash shell保留了前三个文件描述符

Linux的标准文件描述符

文件描述符:缩写:描述
0:STDIN:标准输入
1:STDOUT:标准输出
2:STDERR:标准错误

1.STDIN

STDIN文件描述符代表shell的标准输入
对终端界面来说,标准输入时键盘
shell从STDIN文件描述符对应的键盘获得输入,在用户输入时处理每个字符
使用输入重定向符号(<)时,读取文件并能够提取数据

使用cat命令用testfile文件中的行作为输入

编写testfile文件

This is first line.
This is a test line
This is third line.

执行命令

cat < testfile

2.STDOUT

STDOUT文件描述符代表shell的标准输出
在终端界面上,标准输出就是终端显示器
shell的所有输出会被定向到标准输出中,也就是显示器
默认情况下,大多数bash命令会将输出导向STDOUT文件描述符
也可以使用输出重定向来改变(>)

执行命令

ls -l > test2
cat test2
who >> test2
cat test2
ls -al badfile > test3
cat test3

当执行一个错误的命令时,shell并未将错误消息重定向到文件中

3.STDERR

shell通过特殊字符的STDERR文件描述符来处理错误消息
STDERR文件描述符代表shell的标准错误输出
shell或shell中运行的程序和脚本出错时生成的错误消息都会发送到这个位置
默认情况下,错误消息也会输出到显示器输出中
STDERR并不会随着STDOUT的重定向而发生改变

15.1.2 重定向错误

1.只重定向错误

STDERR文件描述符为2,可以选择只重定向错误消息
将文件描述符放在重定向符号前
该值必须紧紧地放在重定向符号前,否则不会生效

执行命令

ls -al badfile 2> test4
cat test4

也可以组合使用STDOUT和STDERR

执行命令

ls -la test badtest test2 2> test5
cat test5

2.重定向错误和数据

如果想重定向错误和正常输出,必须用两个重定向符号
需要在符号前面放上带重定向数据所对应的文件描述符
然后指向用于保持数据的输出文件

执行命令

ls -al test test2 test3 badtest 2> test6 1>test7
cat test6
cat test7

使用特殊符号(&>)将STDOUT和STDERR的输出重定向到同一个输出文件

执行命令

ls -al test test2 test3 badtest &>test7
cat test7

15.2 在脚本中重定向输出

15.2.1 临时重定向

命令演示:echo "This is an error message" >&2
命令说明:手动生成错误信息并输出重定向到STDERR

编写test8.sh脚本

#!/bin/bash
echo "This is an error" >&2
echo "This is normal output"

执行命令

./test8.sh
./test8.sh 2>test9
cat test9

15.2.2 永久重定向

使用exec命令告诉shell在脚本执行期间重定向某个特定文件描述符

编写test10.sh脚本

#!/bin/bash
exec 1>testout

echo "This is a test of redirecting all output"
echo "from a script to another file"
echo "without having to redirect every individual line"

执行命令

./test10.sh
cat testout

也可以在脚本执行过程中重定向STDOUT

编写test11.sh脚本

#!/bin/bash
exec 2>testerror

echo "this is the start of the script"
echo "now redirecting all output to another location"

exec 1>testout

echo "Theis out should go to the testout file"
echo "but this should go to testerror file" >&2

执行命令

./test11.sh
cat testout
cat testerror

15.3 在脚本中重定向输入

命令演示:exec 0< testfile
命令说明:使用与脚本重定向STDOUT和STDERR相同的方法将STDIN从键盘重定向到其他位置

编写test12.sh脚本

#!/bin/bash
exec 0< testfile
count=1

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

15.4 创建自己的重定向

在脚本中重定向输入和输出时,并不局限这3个默认的文件描述符
在shell中最多可以有9个打开的文件描述符
可以将其他6个从3~8的文件描述符中的任意一个分配给文件

15.4.1 创建输出文件描述符

使用exec命令来给输出分配文件描述符

编写test13.sh脚本

#!/bin/bash

exec 3>test13out

echo "This should display on the monitor"
echo "and this should be stored in the file" >&3
echo "Then this should be back on the monitor"

执行命令

./test13.sh
cat test13out

命令演示:exec 3>>test13out
命令说明:使用exec命令来讲输出追加到现有文件中

15.4.2 重定向文件描述符

在脚本中临时重定向输出,然后恢复默认输出设置

编写test14.sh脚本

#!/bin/bash

exec 3>&1
exec 1>test14out

echo "This should store in the output file"
echo "along with whis line"

exec 1>&3

echo "Now things should be back normal"

执行命令

./test14.sh
cat test14out

这个例子有点叫人抓狂,来一段一段地看。首先,脚本将文件描述符 3 重定向到文件描述符1
的当前位置,也就是 STDOUT 。这意味着任何发送给文件描述符 3 的输出都将出现在显示器上。
第二个 exec 命令将 STDOUT 重定向到文件,shell现在会将发送给 STDOUT 的输出直接重定向到
输出文件中。但是,文件描述符 3 仍然指向 STDOUT 原来的位置,也就是显示器。如果此时将输出
数据发送给文件描述符 3 ,它仍然会出现在显示器上,尽管 STDOUT 已经被重定向了。
在向 STDOUT (现在指向一个文件)发送一些输出之后,脚本将 STDOUT 重定向到文件描述符
3 的当前位置(现在仍然是显示器)。这意味着现在 STDOUT 又指向了它原来的位置:显示器。
这个方法可能有点叫人困惑,但这是一种在脚本中临时重定向输出,然后恢复默认输出设置
的常用方法。

15.4.3 创建输入文件描述符

可以将STDIN文件描述符保存到另外一个文件描述符,然后在读取完文件之后再将STDIN恢复到它原来的位置

编写test15.sh脚本

#!/bin/bash

exec 6<&0
exec 0< testfile

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

exec 0<&6
read -p "Are you done now [Y/N]?" answer
case $answer in
Y|y) echo "Goodbye" ;;
N|n) echo "Sorry,this is the end."
esac

15.4.4 创建读写文件描述符

可以用同一个文件描述符对同一个文件进行读写
在对同一个文件进行数据读写时,shell会维护一个内部指针
任何读或写都会从指针上次的位置开始

编写test16.sh脚本

#!/bin/bash

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

testfile内容

This is the first line.
This is the second line.
This is the third line.

执行命令

cat testfile
./test16.sh
cat testfile

15.4.5 关闭文件描述符

命令格式:exec 3>&-
命令说明:在脚本结束前手动关闭文件描述符,将它重定向到特殊符号&-

在关闭文件描述符时,如果随后在脚本中打开了同一个输出文件,则会覆盖已有文件

编写test17.sh脚本

#!/bin/bash

exec 3> test17file
echo "This is a test line of data" >&3
exec 3>&-

cat test17file

exec 3> test17file
echo "This'll be bad" >&3

执行命令

./test17.sh
cat test17file

15.5 列出打开的文件描述符

使用lsof命令显示已打开的文件描述符

编写test18.sh脚本

#!/bin/bash

exec 3> test18file1
exec 6> test18file2
exec 7< testfile

/usr/bin/lsof -a -p $$ -d0,1,2,6,7

15.6 阻止命令输出

可以将STDERR重定向到null文件的特殊文件
在Linux系统上null文件的标准位置时/dev/null
重定向到该位置的任何数据都会被丢掉
通常用于清除日志文件

命令演示:cat /dev/null > testfile
命令说明:清除testfile文件中的数据

15.7 创建临时文件

15.7.1 创建本地临时文件

命令演示:mktemp testing.XXXXXX
命令说明:mktemp命令创建一个临时文件,会自动用6个字符码替换这6个X,从而保证文件名在目录中是唯一的。且可以创建多个临时文件,每个文件都是唯一的。

编写test19.sh脚本

#!/bin/bash

tempfile=$(mktemp test19.XXXXXX)

exec 3>$tempfile

echo "This script writes to temp file $tempfile"

echo "This is the first line" >&3
echo "This is the second line" >&3
echo "This is the last line" >&3

exec 3>&-

echo "Done creating temp file.The contents are:"
cat $tempfile
rm -f $tempfile 2> /dev/null

执行命令

./test19.sh
ls -al test19*

15.7.2 在/tmp目录创建临时文件

使用-t选项强制mktemp命令在系统的临时目录下创建该文件
mktemp命令会返回该临时文件的全路径

编写test20.sh脚本

#!/bin/bash

tempfile=$(mktemp -t tmp.XXXXXX)

echo "This is a test file." > $tempfile
echo "This is the second line of the test." >> $tempfile
echo "The temp file is located at: $tempfile"

cat $tempfile
rm -f $tempfile

15.7.3 创建临时目录

使用-d选项告诉mktemp命令创建一个临时目录

编写test21.sh脚本

#!/bin/bash

tempdir=$(mktemp -d dir.XXXXXX)
cd $tempdir
tempfile1=$(mktemp temp.XXXXXX)
tempfile2=$(mktemp temp.XXXXXX)
exec 7> $tempfile1
exec 8> $tempfile2

echo "Sending data to directory $tempdir"
echo "This is a test line of data for $tempfile1" >&7
echo "This is a test line of data for $tempfile2" >&8

执行命令

./test21.sh
ls -al
ls -al dir.zKQTCL/
cat dir.zKQTCL/temp.EZBifQ
cat dir.zKQTCL/temp.sO4oa4

15.8 记录消息

将输出同时发送到显示器和日志文件
使用tee命令,相当于管道的一个T型接头
将从STDIN过来的数据同时发往两处
一处是STDOUT,另一处时tee命令所指定的文件名:tee filename

使用-a选项将数据追加到文件中,数据显示在屏幕上的同时再永久保存在文件中

编写test22.sh脚本

#!/bin/bash

tempfile=test22file

echo "This is the start of the test" | tee $tempfile
echo "This is the second line of the test" | tee -a $tempfile
echo "This is the end of the test" | tee -a $tempfile

执行命令

./test22.sh
cat test22file

15.9 实例

案例说明:文件重定向常见于脚本需要读入文件和输出文件。通过读取.csv格式的数据文件,输出SQL INSERT语句来将数据插入数据库

编写members.csv文本

Blum,Richard,123 Main st.,Chicago,IL,60601
Blum,Barbara,123 Main st.,Chicago,IL,60601
Bresnahan,Christine,456 Oak Ave.,Columbus,OH,43201
Bresnahan,Timothy,456 Oak Ave.,Columbus,OH,43201

编写test23.sh脚本

#!/bin/bash

outfile='members.sql'
IFS=','

while read lname fname address city state zip in ${1}
do
    cat >> $outfile << EOF
    INSERT INTO members (lname,fname,address,city,state,zip) 
    VALUES('$lname','$fname','$address','$city','$state','$zip');
EOF
done

执行命令

./test23.sh < members.csv
cat members.sql

15.10 小结

bash shell允许在脚本中创建自己的文件描述符。使用mktemp可以很方便的创建临时目录及文件。tee命令便于将输出同时发送给标准输出和日志文件。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,254评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,875评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,682评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,896评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,015评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,152评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,208评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,962评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,388评论 1 304
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,700评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,867评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,551评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,186评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,901评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,142评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,689评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,757评论 2 351

推荐阅读更多精彩内容

  • 第十五章:呈现数据 本章内容 15.1 理解输入和输出 两种显示脚本输出的方法 15.1.1 标准文件描述符 Li...
    数据萌新阅读 293评论 0 0
  • 一、Python简介和环境搭建以及pip的安装 4课时实验课主要内容 【Python简介】: Python 是一个...
    _小老虎_阅读 5,735评论 0 10
  • 官网 中文版本 好的网站 Content-type: text/htmlBASH Section: User ...
    不排版阅读 4,380评论 0 5
  • .bat脚本基本命令语法 目录 批处理的常见命令(未列举的命令还比较多,请查阅帮助信息) 1、REM 和 :: 2...
    庆庆庆庆庆阅读 8,076评论 1 19
  • 今日打卡1:共计打卡59分钟 论证本身不会强迫我们去关注什么 再合理的结构也不能带给具有错误前提的论证新生。 如果...
    吟_f3da阅读 197评论 0 0