《Linux命令行与shell脚本编程大全》第十五章 呈现数据
15.1 理解输入和输出
现在知道两种显示脚本输出的方法
1)在显示器屏幕上显示
2)将输出文件重定向到文件中
15.1.1 标准文件描述符
Linux系统将每个对象当做文件处理。这包括输入和数出进程。
Linux用文件描述符来标识每个文件对象。
它是一个非负整数,可以唯一标识会话中打开的文件。
每个进程一次最多可以有九个文件描述符
bash shell保留的前3个文件描述符(0、 1、 2)
1.STDIN 标准输入(0)
STDIN文件代表shell的标准输入。
对终端界面来说,标准输入是键盘。
shell从STDIN文件描述符对应的键盘获得输入,在用户输入时处理每个字符
在使用输入重定向符号( < )时,Linux会用重定向指定的文件来替换标准输入文件描述符。它会读取文件并提取数据,就如同它是键盘上键入的。
2.STDOUT 标准输出(1)
STDOUT文件描述符代表shell的标准输出。
对终端界面来说,标准输出是终端显示器。shell的所有输出会被定向到标准输出中。
也可以通过输出重定向( > )来改变输出。通过输出重定向符号,可以将本来显示在显示器上的输出重定向到指定的文件。
>> 表示追加到文件
注意:用了输出重定向,shell并未将错误消息重定向到输出重定向文件中。错误消息仍会显示在显示器中。
3.STDERR 标准错误(2)
STDERR文件描述符来处理错误消息。
shell或shell中运行的程序和脚本出错时生成的错误消息都会发送到这个位置。
默认情况下STROUT和STDERR指向同样的地方(显示器)。但是STDERR不会随着STDOUT重定向而发生改变。
15.1.2 重定向错误
1.只重定向错误
将该文件描述符值(2)放在重定向符号(>)前面,必须挨着,不能有空格。
比如,查看一个不存在的文件:
$ls –al 2> log.txt
这种方法只会重定向错误消息,普通输出不会被重定向。
2. 重定向错误和数据
需要用两个重定向符号,需要在符号前面放上待重定向数据所对应的文件描述符,然后指定用于保存数据的输出文件。
例如:
$ls -al test1 test2 test3 badfile 2> ErrLog.txt 1> DataLog.txt
表示将错误信息重定向到ErrLog.txt,正常输出重定向到DataLog.txt。
这样错误信息和正常输出就分开在两文件了。
$ls -al test1 test2 test3 badfile &> AllLog.txt
这样表示将STDOUT和STDERR重定向到同一个文件AllLog.txt中了。
bash shell自动赋予了错误消息更高的优先级,这样可以集中浏览错误信息了。
15.2 在脚本中重定向输出
有两种方法:
1)临时重定向行输出
2)永久重定向脚本中的所有命令
15.2.1 临时重定向
可以单独将一行重定向到STDERR。
比如:
echo “this is error msg” >&2
echo “this is normal msg”
正常运行不会看出什么,但是假如运行时重定向了STDERR就有意思了。
$./test 2> Error.txt
就可以看到第一行输出到了 Error.txt。而正常输出还是在屏幕上。
15.2.2 永久重定向
如果有大量数据需要重定向,那么就会比较麻烦。
新方法:用exec命令告诉shell在脚本执行期间重定向某个特定文件描述符
直接上例子:
1 #!/bin/bash
2 echo "this is error msg step1" >&2
3 echo "this is normal msg step1"
4 # 上面没有重定向,所以还是在屏幕输出。下面才开始重定向到需要的文件中
5 exec 1>test2log.txt
6 exec 2>test2Error.txt
7 echo "this is error msg step2" >&2
8 echo "this is normal msg step2"
这样一旦重定向了就很难改回去了。
15.3 在脚本中重定向输入
exec 命令允许你将STDIN重定向到Linux系统上的文件中。
例子:查看test2中的数据
1 #!/bin/bash
2 exec 0< test2 # 输入重定向到test2中
3 echo "test2:"
4 count=1
5 while read line
6 do
7 echo " $line"
8 count=$[ $count + 1 ]
9 done
15.4 创建自己的重定向
之前说一个进程最多可以与9个打开的文件描述符。其他6个(3 ~ 8)的文件描述符均可用作输入或输出重定向。
可以将这些文件描述符中的任意一个分配给文件。
15.4.1 创建输出文件描述符
用exec命令给输出分配文件描述符。
和标准的文件描述符一样,一旦将另一个文件描述符分配给了一个文件,这个重定向就会一直有效,直到你重新分配。
例子:
1 #!/bin/bash
2 exec 3>test4log.txt # exec 3>>test4log.txt 这个是将输出追加到现有文件
3 echo "This is Normal msg"
4 echo "This is fd:3 msg" >&3
15.4.2 重定向文件描述符
现在介绍怎么恢复已重定向的文件描述符。
可以分配另外一个文件描述符给标准文件描述符,反之亦然。
可以将STDOUT重定向到另外一个文件描述符,然后再利用该文件描述符重定向回STDOUT
例子:
1 #!/bin/bash
2 # storing STDOUT, then coming back to it
3 exec 3>&1 # 3重定向到STDOUT。意味着给3的数据都将出现再显示器上
4 exec 1>test5log.txt # 将STDOUT重定向到文件。但是3仍然指向STDOUT原来的位置,也就是显示器。这时给3发会显示在显示器中。给STDOUT发会显示在文件中
5 echo "This should store in the output file"
6 echo "alone with this line."
7
8 exec 1>&3 # 将STDOUT重定向到3的当前位置(也就是显示器)
9 echo "now things should be back to normal"
15.4.3 创建输入文件描述符
跟上面类似,先将STDIN保存到另外一个文件描述符,然后读取完文件在将STDIN恢复
例子:
1 #!/bin/bash
2 exec 6<&0 # 6先保存STDIN的位置
3 exec 0<test5 # 将STDIN重定向到 test5
4 count=1
5 while read line
6 do
7 echo " $line"
8 count=$[ $count +1 ]
9 done
10
11 exec 0<&6 # 读取完成后将STDIN重定向到文件描述符6,从而恢复之前的位置
12 read -p "Are you done now?" answer
13 case $answer in
14 Y|y) echo "GoodBye!!!";;
15 N|n) echo "Sorry, this is the end";;
16 *) echo "Error End";;
17 esac
15.4.4 创建读写文件描述符
可以打开单个文件描述符作为输入和输出。可以利用同一个文件描述符对同一个文件进行读写。
用起来要小心:由于是对同一个文件进行数据读写,shell会维护一个内部指针,指明在文件中的当前位置。任何读或写都是从文件指针上次的位置开始。
例子:
1 #!/bin/bash
2 exec 3<> testfile
3 read line <&3
4 echo "Read:$line" #注意这里写是从文件指针上次的位置开始,也就是读了一行之后的位置
5 echo "Write: This is test line" >&3
15.4.5 关闭文件描述符
如果你创建了新的输入或输出文件描述符,shell会在脚本退出时自动关闭它们。
但是某些时候还是要自己去关闭。
如何关闭: 将要关闭的文件描述符重定向到特殊符号 &-
一旦关闭后,就不能在脚本中向他写入数据,否则shell会产生错误信息。
例子:
1 #!/bin/bash
2 # close fd test
3 exec 3>test8log.txt
4 echo "This is normal to fd:3" >&3
5 exec 3>&-
6 echo "after close write:his is normal to fd:3" >&3 # 关闭后再往里面写会出错
7
8 exec 3>test8log.txt # 这里相当于重新打开了
9 echo "This is bad normal to fd:3" >&3 # 会覆盖原来的
15.5 列出打开的文件描述符
lsof命令会列出整个linux系统打开的所有的文件描述符。会产生大量输出。
还可以接选项和参数:
-p 后面接要查看的进程。 $$ 表示当前进程
-d 后面指定要显示的文件描述符编号。
例子:
1 #!/bin/bash
2 exec 3> testfile
3 lsof -a -p $$ -d 0,1,2,3,4
15.6 阻止命令输出
有时不想显示脚本的输出。可以将输出重定向到一个叫做null文件的特殊文件中去。
比如:
$ls –al > /dev/null
还可以这样清空日志文件
$ cat /dev/null > TestLog.txt
15.7 创建临时文件
linux使用/tmp目录来存放不需要永久保留的文件。大部分linux发行版配置了系统在启动时自动删除/tmp目录下的所有文件。
系统上的任何用户账户都有权限在读写/tmp目录中的文件。
mktemp可以在/tmp目录中创建一个唯一的临时文件。一旦创建了文件,你就在脚本中有了完整的读写权限,别人无法访问它。
15.7.1 创建本地临时文件
只需要指定一个文件名模板就行了,在文件末尾加上6个X。
$mktemp testing.XXXXXX
注意:这里一定要有大写的X。这里的X有点通配符的意思。还可以写不是X的
mktemp命令的输出是它所创建的文件的名字。在脚本中保存起来,就能在后面的脚本里引用了。
例子:
1 #!/bin/bash
2 # create and using temp file
3 tempfile=$(mktemp test10.XXXXXX)
4 echo "tempfile = $tempfile"
5 exec 3>$tempfile
6 echo "This script writes to tmp file $tempfile"
7 echo "this is first line" >&3
8 echo "this is second line" >&3
9 echo "this is third line" >&3
10 exec 3>&-
11
12 echo "Now delete file $tempfile"
13 rm -f $tempfile > /dev/null
15.7.2 在/tmp目录创建临时文件
-t 选项会强制mktemp在系统的临时目录来创建该文件。
这个时候返回用来创建临时文件的全路径,而不是只有文件名。
就上面的例子加上 –t就好了。
。。。
tempfile=$(mktemp -t test10.XXXXXX)
。。。
15.7.3 创建临时目录
-d选项用来创建临时目录。这样就能用改目录进行任何需要的操作了。
例子:
1 #!/bin/bash
2 # create and using temp dir
3 tempdir=$(mktemp -d test12dir.12XXXX)
4 cd $tempdir
5 echo This in Dir:$(pwd)
6 tempfile=$(mktemp test12.XXXXXX)
7 echo "tempfile = $tempfile"
8 exec 3>$tempfile
9 echo "This script writes to tmp file $tempfile"
10 echo "this is first line" >&3
11 echo "this is second line" >&3
12 echo "this is third line" >&3
15.8 记录消息
将输出同时发送到显示器和日志文件,需要特殊命令tee就可以了。
tee命令相当于管道第一个T型接头。它将STDIN过来的数据同时发往两处,一处是STDOUT,一处是指定的文件。
比如:
$date | tee log.txt
$date | tee –a log.txt # 这个是将数据追加到文件中
例子:
1 #!/bin/bash
2 # tee test
3 echo "This is 1 msg" | tee test13log.txt
4 echo "This is 2 msg" | tee -a test13log.txt
5 echo "This is 3 msg" | tee -a test13log.txt
15.9 实例
文件重定向常见于脚本需要读入文件和输出文件时。
需求:把数据数据放入电子表格中(.csv文件),读取文件,创建INSERT语句。
例子:
1 #!/bin/bash
2 outfile='members.sql'
3 IFS=,
4 while read name age sex num
5 do
6 cat >> $outfile << EOF
7 insert into members (name, age, sex, num) values('$name', '$age', '$sex', '$num');
8 EOF
9 done <${1}
1)${1}代表第一个命令行参数。它指明了待读取数据的文件。
2)read会用IFS字符解析读入的文本,我们在这里将IFS指定为逗号。
cat >> $outfile << EOF // 这一段还是不大理解
这个包含一个输出追加重定向(>>)和一个输入追加重定向(<<)。
>> 将cat命令的输出追加到由$outfile变量指定的文件中。
cat命令的输入不在取自标准输入,而是被重定向到脚本中存储的数据。
EOF符号标记了追加到文件中的数据的起止。
输入文件 + 运行 + 结果:
说明:
特殊重定向(here document):
command << delimiter
document
delimiter
作用是将两个delimiter之间的内容(document)作为输入传给command
注意:结尾的delimiter一定要顶格写,不能有空格。
(1)
6 cat >> $outfile << EOF
7 insert into members (name, age, sex, num) values('$name', '$age', '$sex', '$num');
8 EOF
(2)
6 cat << EOF
7 insert into members (name, age, sex, num) values('$name', '$age', '$sex', '$num');
8 EOF
黄色高亮部分作为输入传给cat。(1)重定向到outfile去了,(2)仍然是标准输出(屏幕)
《Linux命令行与shell脚本编程大全》第十五章 呈现数据的更多相关文章
- 《Linux命令行与shell脚本编程大全》 第五章理解shell
5.1 1. cat /etc/passwd 可以查看每个用户自己的默认的shell程序. 2.默认的交互shell会在用户登录某个虚拟控制台终端时启动. 不过还有另外一个默认的shell是/bin/ ...
- 《Linux命令行与shell脚本编程大全》 第二十七章 学习笔记
第二十七章:shell脚本编程进阶 监测系统统计数据 系统快照报告 1.运行时间 uptime命令会提供以下基本信息: 当前时间 系统运行的天数,小时数,分钟数 当前登录到系统的用户数 1分钟,5分钟 ...
- 《Linux命令行与shell脚本编程大全》 第二十三章 学习笔记
第二十三章:使用数据库 MySQL数据库 MySQL客户端界面 mysql命令行参数 参数 描述 -A 禁用自动重新生成哈希表 -b 禁用 出错后的beep声 -B 不使用历史文件 -C 压缩客户端和 ...
- 《Linux命令行与shell脚本编程大全》 第六章环境变量
很多程序和脚本都通过环境变量来获取系统信息.存储临时数据和配置信息. 6.1 什么是环境变量: bash shell用一个叫环境变量(environment variable)的特性来存储有关shel ...
- 《Linux命令行与shell脚本编程大全》第十三章 更多的结构化命令
本章讨论bash shell的循环命令for.while和until 13.1 for命令 重复执行一系列命令在编程中很常见. bash shell提供了for命令,允许你创建一个遍历一系列值的循环. ...
- 《Linux命令行与shell脚本编程大全》第二十一章 sed进阶
本章介绍一些sed编辑器提供的高级特性. 21.1 多行命令 按照之前的知识,所有的sed编辑器命令都是针对单行数据执行操作的. 在sed编辑器读取数据流时,它会基于换行符的位置将数据分成行,一次处理 ...
- 《Linux命令行与shell脚本编程大全》第十一章 构建基本脚本
11.1使用多个命令 $date;who // 命令列表,加入分号就可以,这样会依次执行.参见5.2.1节 注意区分$(date;who),这个是进程列表,会生成一个子shell来执行 Shel ...
- 《Linux命令行与shell脚本编程大全》 第三章 学习笔记
第三章:基本的bash shell命令 bash程序使用命令行参数来修改所启动shell的类型 参数 描述 -c string 从string中读取命令并处理他们 -r 启动限制性shell,限制用户 ...
- 《Linux命令行与shell脚本编程大全》第十七章 创建函数
可以将shell脚本代码放进函数中封装起来,这样就能在脚本中的任何地方多次使用它了. 17.1 基本的脚本函数 函数:是一个脚本代码块,可以为其命名并在代码中任何位置重用. 17.1.1 创建函数 有 ...
- 《Linux命令行与shell脚本编程大全》 第七章理解Linux文件权限
Linux沿用了Unix文件权限的方法,允许用户和组根据每个文件和目录的安全性设置来访问文件. 用户权限通过创建用户时分配的用户ID(UID)来跟踪的.每个用户有唯一的ID,但是登录时用的不是UID, ...
随机推荐
- 前端工程化grunt
1.grunt是什么? grunt是基于nodejs的前端构建工具.grunt用于解决前端开发的工程问题. 2.安装nodejs Grunt和所有grunt插件都是基于nodejs来运行的. 安装了n ...
- hibernate5使用注解遇到的问题
问题描述 出现MappingException:Unknown entity,看到这个我以为在cfg配置文件中没有配置,实际上我是配置了的,那么问题出在那里呢,既然找不到实体,那么会不会是注解类出现了 ...
- Debian 9 中手动设置有线网络
multi-user.target中不使用networkmanager,上网需要手动设置后才可以,进行有线网线的设置: 首先得到网卡名称:ip addr or ls /sys/class/net/,以 ...
- 用node.js实现ORM的一种思路
ORM是O和R的映射.O代表面向对象,R代表关系型数据库.二者有相似之处同时也各有特色.就是因为这种即是又非的情况,才需要做映射的. 理想情况是,根据关系型数据库(含业务需求)的特点来设计数据库.同时 ...
- netbeans 字体发虚
今天更新了netbeans,重启后蛋疼了,字体发虚,搜索网络后有得到如下方案: 对Archlinux,去/usr/share/netbeans/etc,里面找到netbeans.conf,给下面一行参 ...
- Spring 笔记总结
1.Spring框架的核心是提供一个容器(BeanFactory 或 ApplicationContext),提供以下功能: 1)创建和销毁组件对象,类似"工厂类" 2)采用不同的 ...
- [Linux 使用(2)] 64位Linux下安装jboss-as-7.1 以及jdk1.7
一.软件的下载 jdk下载地址: http://www.oracle.com/technetwork/java/javase/downloads/jdk7-downloads-1880260.h ...
- Oracle 表空间扩充
Oracle 表空间扩充 一.现场环境: (1)操作系统:AIX (2)数据库:Oracle Database 10g Enterprise Edition Release 10.2.0.5.0 - ...
- ssh连接虚拟机失败解决办法
首先,你需要知道本机IP跟虚拟机IP,然后让两者互相ping一下,看能否ping通 让主机ping虚拟机 :ping (虚拟机ip) 出现如下: 表示主机可以ping通虚拟机 然后让虚拟机ping主机 ...
- return flase 作用
调用return false的时候,他实际上做了三件事 event.preventDefault(); 禁止默认行为 event.stopPropagation(); 阻止冒泡 ...