我在刚开始接触IO重定向时,经历了由懂到不懂然后了然的过程,当然现在的我也不可能说对于IO重定向就彻底懂了,只是在解决一些问题或实现某些结果时不会因为IO重定向的问题而迷惑了。 什么叫IO重定向? 为了解释这个问题,我们要先明白什么叫IO,什么叫做程序的数据流。 什么叫IO? 在Linux或计算机领域IO指的是信息的输入和输出。 在Linux中可用于输入的设备:文件(Linux中一切皆文件) 具体包括:键盘设备、文件系统上的常规文件、网卡等。 在Linux中用于输出的设备:文件 具体包括:显示器、文件系统上的常规文件、网卡等。 什么叫做数据流? 我们通常描述的信息本质上来说都是数据,因为信息处于动态,我们就将信息或者命令等概念称作流动的数据也就是数据流。 数据流分为输入流(InputStream)和输出流(OutputStream)两类。输入流只能读不能写,而输出流只能写不能读。通常程序中使用输入流读出数据,输出流写入数据,就好像数据流入到程序并从程序中流出。采用数据流使程序的输入输出操作独立与相关设备。输入流可从键盘或文件中获得数据,输出流可向显示器、打印机或文件中传输数据。 在Linux中,程序的数据流有三种: 输入的数据流:标准输入STDIN常用设备:键盘 输出的数据流:标准输出STDOUT常用设备:终端 错误输出流:错误输出STDERR常用设备:终端 在Linux中打开一个文件,在该文件被加载完成后对于系统来说需要用一个数字表示,这个数字叫做fd:filedescriptor文件描述符。 因为Linux系统中一切皆文件,所以对应的标准输入设备,标准输出设备,错误输出设备都有其对应的fd 标准输入:0 标准输出:1 错误输出:2 IO重定向的意思就是将系统原本默认的输入输出的路径重新定向到其他文件。 我知道解释到这里还是会很困惑,别着急,这个概念需要通过一定量的实验来说明。 -------------------------------------------------------------------------------- 输出重定向 其常用、、这三种表示 :覆盖输出:追加输出:强行覆盖 因为使用不当会对原有的数据造成很大的影响,所以有时候我们会手动设定关闭的特性。其命令为: set-C禁止覆盖输出重定功能 set+C为开启覆盖输出重定向功能 不过上述命令对“”无效 下面以具体实验来说明上面内容 实验环境:在/test/目录下 []#ll 总用量0 []#echo$(date)t1 []#ll 总用量4 -rw-r--r--.1rootroot438月218:15t1 []#catt1 2016年08月02日星期二18:15:28CST []#echotestt1 []#catt1 test []#echo$(who)t1 []#catt1 test root:02016-08-0210:12(:0)rootpts/02016-08-0210:12(192.168.85.1)rootpts/12016-08-0210:19(192.168.85.1) []#set-C []#echo111t1 -bash:t1:无法覆盖已存在的文件 []#echo111t1 []#catt1 111 上面的结果显示了、、三者的各自功能 相信看到这里对于输入重定向会有了进一步的认识。 -------------------------------------------------------------------------------- 错误输出流重定向 2 []#echoo1t2 bash:echoo:未找到命令... 当命令错误时,shell会返回错误信息,若我们想将错误信息存到某个文件则可按如下操作 []#echoo12t2 -bash:t2:无法覆盖已存在的文件 []#ll 总用量4 -rw-r--r--.1rootroot48月218:18t1 -rw-r--r--.1rootroot08月218:20t2 []#echoo12t3 []#catt3 bash:echoo:未找到命令... []#echopwqew2t3 []#catt3 bash:echoo:未找到命令... 相似命令是:echo bash:echop:未找到命令... 错误重定向也支持追加。 如果我们不管命令对错都想记录那么可以使用如下格式实现: 1、、 []#ech2t4 []#echorightt4 []#catt4 bash:ech2:未找到命令... right 2、command/path/somewhere...21第二种只能为此种格式,不管前面是追加还是覆盖后面均为21。21为错误格式,使用后在CentOS7.2下会报错。 []#ech2t521 []#echorightt521 []#catt5 bash:ech2:未找到命令... right 注:输出重定向的对象可以是各种文件,但不能将其定向至命令的输入,要想实现这个功能则需要用管道。这里大家可能有点迷,下面以例子说明 []#whotra-zA-Zt6 []#catt6 rootpts/02016-08-0210:12(192.168.85.1) []#ll 总用量4 -rw-r--r--.1rootroot548月218:53t6 -rw-r--r--.1rootroot08月218:53tr 我们将who显示的命令重定向至tr命令的输入,之后将内容小写转换为大写后再重定向至t6文件。我们想实现的是这个结果,但是并没有实现,反而在过程中出现了tr这个文件。这是因为在第一层的重定向中,默认将tr当做文件名,但是奇怪的是tr内什么都没有,所以这种错误的理解尽早摆脱。 []#cattr []# 我们可以使用管道完美解决上面的问题。 []#whotra-zA-Zt6 []#catt6 ROOT:02016-08-0210:12(:0) ROOTPTS/02016-08-0210:12(192.168.85.1) ROOTPTS/12016-08-0210:19(192.168.85.1) 什么是管道,我相信通过上面的例子大家应该对它有了个初步的认知。 管道:连接程序,实现将前一个命令的输出直接定向后一个程序当做输入数据流。 其常用表达格式如下:COMMAND1COMMAND2COMMAND3... 它是输出重定向的补充与加强,其本质还是类属于输出重定向。 既然说道管道,这里再多补充点 常用于管道的命令: tee tee-readfromstandardinputandwritetostandardoutputandfiles 显示标准输入的结果并将其写入文件 tee的使用格式: 命令1tee文件名命令2 把命令1的STDOUT保存在文件名中,然后管道输入给命令2 作用: 保存不同阶段的输出 复杂管道的故障排除 同时查看和记录输出 下面通过一个简单的例子说明tee的具体作用 []#whoteet2tra-zA-Z ROOT:02016-08-0210:12(:0) ROOTPTS/02016-08-0210:12(192.168.85.1) ROOTPTS/12016-08-0210:19(192.168.85.1) []#catt2 root:02016-08-0210:12(:0) rootpts/02016-08-0210:12(192.168.85.1) rootpts/12016-08-0210:19(192.168.85.1) tee可以将前一个的结果记录在t2文件内,同时显示后一个命令的结果。 -------------------------------------------------------------------------------- 输入重定向 单行模式、多行模式 要了解输入重定向,我们得先了解一个命令 tr tr-translateordeletecharacters转换或删除字符 其表达格式如下: tr[OPTION]...SET1[SET2] 选项: -c或complerment:取字符集的补集 -d或delete:删除所有属于第一字符集的字符 -s或squeeze-repeats:把连续重复的字符以单独一个字符表示 下面我们通过一个例子简要了解下tr的作用 12345678[]#catt1 root:02016-08-0210:12(:0) rootpts/02016-08-0210:12(192.168.85.1) rootpts/12016-08-0210:19(192.168.85.1) []#tra-zA-Zt1 ROOT:02016-08-0210:12(:0) ROOTPTS/02016-08-0210:12(192.168.85.1) ROOTPTS/12016-08-0210:19(192.168.85.1) t1是上面tee存储的who内容,我们通过输入重定向将其作为tr的输入,并由小写转换为大写。 输入重定向就是将原来用键盘输入的内容通过其他文本内容或文件内容代替。 我想大家对于多行重定向有些不理解,这里再对多行重定向在以例子说明一下。 12345678[~]#tra-zA-Zend morning,boys todayisanotherday pleasebehappy end MORNING,BOYS TODAYISANOTHERDAY PLEASEBEHAPPY 多行输入重定向后面需要接规定的结尾字符串,通常使用eof或end为结尾标示符。 多行输入重定向需要手动键入内容。单行输入重定向则需要跟文件或前一个命令的输出结果。 -------------------------------------------------------------------------------- 我知道看到这里依然会有点懵,下面通过9个实例来综合使用标准输出输入及管道命令。 实���环境CentOS7.2 1、将/etc/issue文件中的内容转换为大写后保存至/test/issue#文件中 1234567[]#cat/etc/issuetra-zA-Z/test/issue1 []#echo$(tra-zA-Z/etc/issue)/test/issue2 []#catissue1 \S KERNEL\RONAN\M []#catissue2 \SKERNEL\RONAN\M 上面两种方式均可以实现要求,只不过输出格式略有不同,这根命令有关。在没有进一步的限制下,这两种表达方式均可。第一种使用管道,输出重定向,第二种使用命令引用,输入重定向及输出重定向。 2、将当前系统登录用户的信息转换为大写后保存至/test/t2文件中 12345[]#whotra-zA-Z/test/t2 []#catt2 ROOT:02016-08-0210:12(:0) ROOTPTS/02016-08-0210:12(192.168.85.1) ROOTPTS/12016-08-0210:19(192.168.85.1) 3、一个linux用户给root发邮件,要求邮件标题为”help”,邮件正文如下: Hello,Iam用户名,thesystemversionishere,pleasehelpmetocheckit,thanks! 操作系统版本信息 我们使用用户gentoo [~]#sugentoo []$whoami gentoo []$cd/home/gentoo/ []$echo-eHello,Iam`whoami`\nThesystemversionishere,pleasehelpmetocheckit,thanks.\nTheversionis`cat/etc/RedHat-release`mail-shelproot []$exit exit 您在/var/spool/mail/root中有新邮件 HeirloomMailversion12.57/5/10.Type?forhelp. /var/spool/mail/root:3messages1new ueAug209:3821/731help 2rootTueAug209:4421/741help ueAug219:3720/737help 3 Message3: ldomainTueAug219:37:362016 Return-Path:ldomain X-Original-To:root Delivered-To:.localdomain Date:Tue,02Aug201619:37:36+0800 To:.localdomain Subject:help User-Agent:Heirloommailx12.57/5/10 Content-Type:text/plain;charset=us-ascii From:ldomain Status:R -eHello,Iamgentoo Thesystemversionishere,pleasehelpmetocheckit,thanks. TheversionisCentOSLinuxrelease7.2.1511(Core) 这里使用了命令替换来显示用户及版本信息,管道将第一个命令的输出递给下一个命令作为其输入。 4、将/root/下文件列表,显示成一行,并文件名之间用空格隔开 []#ls-1/roottr\n\n anaconda-ks.cfgCSTdead.letterfileinitial-setup-ks.cfgtest.txttr公共模板视频图片文档下载音乐桌面[]# 上面命令已经满足我们的要求了,只不过不换行看着有些别扭,下面我们在完善下使其输出看着更舒服些。 []#echo-e`ls-1/root/tr\n\n` anaconda-ks.cfgCSTdead.letterfileinitial-setup-ks.cfgtest.txttr公共模板视频图片文档下载音乐桌面 []# 使用echo的-e开启转义符使换行\n生效。 5、file1文件的内容为:””计算出所有数字的总和 []#catfile1 ^C []#catfile1 先创建file1文件夹并输入题目要求内容。 12[]#catfile1tr+bc 55 6、处理字符串“xt.,l1jr#!$mn2c*/fe3uz4”,只保留其中的数字和空格 []#echoxt.,l1jr#!$mn2c*/fe3uz4tr-cd[:digit:][:space:] 1234 这里使用了tr中的-c及-d补集跟删除,灵活使用补集概念可以更准确的帮助我们过滤不需要的信息。 7、将PATH变量每个目录显示在独立的一行 []#echo${PATH} /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin []#echo${PATH}tr:\n /usr/local/sbin /usr/local/bin /usr/sbin /usr/bin /root/bin 这个题很简单只需要将PATH正确显示出来,使用tr将:替换为换行即可 8、删除指定文件的空行 这里我们创建一个含有很多空行的文本文件t9 []#catt9 q ere s df sd sd []#catt9tr-s\n q ere s df sd sd 这里使用了tr的重复删除-s选项。 9、将文件中每个单词(字母)显示在独立的一行,并无空行 这里我们选择/etc/rc.d/rc0.d/K50netconsole文件,使用head查看下其文件前5行都什么内容 []#head-5/etc/rc.d/rc0.d/K50netconsole #!/bin/bash # #netconsoleThisloadsthenetconsolemodulewiththeconfiguredparameters. # #chkconfig:-5050 []#cat/etc/rc.d/rc0.d/K50netconsoletr-cs[:alpha:]\nhead-5 bin bash netconsole This 从结果来看我们实现了题目的要求,不过为什么第一行是空行,这是因为-s是将所有的空行压缩为一行,因此前面会留有一行空行。 本文永久更新链接地址: Linux公社简介-广告服务-网站地图-帮助信息-联系我们 本站(LinuxIDC)所刊载文章不代表同意其说法或描述,仅为提供更多信息,也不构成任何建议。 推荐: |