注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

谷搜互联网应用www.iguso.com

谷搜专注企业邮箱十二年

 
 
 

日志

 
 

双向重导向: tee  

2014-05-30 15:50:29|  分类: 技术文章 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

想个简单的东西,我们由前一节知道 > 会将资料流整个传送给档案或装置,因此我们除非去读取该档案或装置, 否则就无法继续利用这个资料流。万一我想要将这个资料流的处理过程中将某段讯息存下来,应该怎么做? 利用 tee 就可以啰~我们可以这样简单的看一下:

  

tee 的工作流程示意图

 

  图 6.3.1、tee 的工作流程示意图

  tee 会同时将资料流分送到档案去与屏幕 (screen);而输出到屏幕的,其实就是 stdout ,可以让下个指令继续处理喔!

  [root@www ~]# tee [-a] file

  选项与参数:

  -a :以累加 (append) 的方式,将资料加入 file 当中!

  [root@www ~]# last | tee last.list | cut -d " " -f1

  # 这个範例可以让我们将 last 的输出存一份到 last.list 档案中;

  [root@www ~]# ls -l /home | tee ~/homefile | more

  # 这个範例则是将 ls 的资料存一份到 ~/homefile ,同时萤幕也有输出讯息!

  [root@www ~]# ls -l / | tee -a ~/homefile | more

  # 要注意! tee 后接的档案会被覆盖,若加上 -a 这个选项则能将讯息累加。

  tee 可以让 standard output 转存一份到档案内并将同样的资料继续送到萤幕去处理! 这样除了可以让我们同时分析一份资料并记录下来之外,还可以作为处理一份资料的中间暂存档记录之用! tee 这傢伙在很多选择/填充的认证考试中很容易考呢!

  字元转换命令: tr, col, join, paste, expand

  我们在 vim 程式编辑器当中,提到过 DOS 断行字元与 Unix 断行字元的不同,并且可以使用 dos2unix 与 unix2dos 来完成转换。好了,那么思考一下,是否还有其他常用的字元替代? 举例来说,要将大写改成小写,或者是将资料中的 [tab] 按键转成空白键?还有,如何将两篇讯息整合成一篇? 底下我们就来介绍一下这些字元转换命令在管线当中的使用方法:

  tr

  tr 可以用来删除一段讯息当中的文字,或者是进行文字讯息的替换!

  [root@www ~]# tr [-ds] SET1 ...

  选项与参数:

  -d :删除讯息当中的 SET1 这个字串;

  -s :取代掉重复的字元!

  範例一:将 last 输出的讯息中,所有的小写变成大写字元:

  [root@www ~]# last | tr '[a-z]' '[A-Z]'

  # 事实上,没有加上单引号也是可以执行的,如:『 last | tr [a-z] [A-Z] 』

  範例二:将 /etc/passwd 输出的讯息中,将冒号 (:) 删除

  [root@www ~]# cat /etc/passwd | tr -d ':'

  範例叁:将 /etc/passwd 转存成 dos 断行到 /root/passwd 中,再将 ^M 符号删除

  [root@www ~]# cp /etc/passwd /root/passwd && unix2dos /root/passwd

  [root@www ~]# file /etc/passwd /root/passwd

  /etc/passwd: ASCII text

  /root/passwd: ASCII text, with CRLF line terminators <==就是 DOS 断行

  [root@www ~]# cat /root/passwd | tr -d '\r' > /root/passwd.linux

  # 那个 \r 指的是 DOS 的断行字元,关于更多的字符,请参考 man tr

  [root@www ~]# ll /etc/passwd /root/passwd*

  -rw-r--r-- 1 root root 1986 Feb 6 17:55 /etc/passwd

  -rw-r--r-- 1 root root 2030 Feb 7 15:55 /root/passwd

  -rw-r--r-- 1 root root 1986 Feb 7 15:57 /root/passwd.linux

  # 处理过后,发现档案大小与塬本的 /etc/passwd 就一致了!

  其实这个指令也可以写在『正规表示法』裡头!因为他也是由正规表示法的方式来取代资料的! 以上面的例子来说,使用 [] 可以设定一串字呢!也常常用来取代档案中的怪异符号! 例如上面第叁个例子当中,可以去除 DOS 档案留下来的 ^M 这个断行的符号!这东西相当的有用!相信处理 Linux & Windows 系统中的人们最麻烦的一件事就是这个事情啦!亦即是 DOS 底下会自动的在每行行尾加入 ^M 这个断行符号!这个时候我们可以使用这个 tr 来将 ^M 去除! ^M 可以使用 \r 来代替之!

  col

  [root@www ~]# col [-xb]

  选项与参数:

  -x :将 tab 键转换成对等的空白键

  -b :在文字内有反斜线 (/) 时,仅保留反斜线最后接的那个字元

  範例一:利用 cat -A 显示出所有特殊按键,最后以 col 将 [tab] 转成空白

  [root@www ~]# cat -A /etc/man.config <==此时会看到很多 ^I 的符号,那就是 tab

  [root@www ~]# cat /etc/man.config | col -x | cat -A | more

  # 嘿嘿!如此一来, [tab] 按键会被取代成为空白键,输出就美观多了!

  範例二:将 col 的 man page 转存成为 /root/col.man 的纯文字档

  [root@www ~]# man col > /root/col.man

  [root@www ~]# vi /root/col.man

  COL(1) BSD General Commands Manual COL(1)

  N^HNA^HAM^HME^HE

  c^Hco^Hol^Hl - filter reverse line feeds from input

  S^HSY^HYN^HNO^HOP^HPS^HSI^HIS^HS

  c^Hco^Hol^Hl [-^H-b^Hbf^Hfp^Hpx^Hx] [-^H-l^Hl _^Hn_^Hu_^Hm]

  # 你没看错!由于 man page 内有些特殊按钮会用来作为类似特殊按键与颜色显示,

  # 所以这个档案内就会出现如上所示的一堆怪异字元(有 ^ 的)

  [root@www ~]# man col | col -b > /root/col.man

  虽然 col 有他特殊的用途,不过,很多时候,他可以用来简单的处理将 [tab] 按键取代成为空白键! 例如上面的例子当中,如果使用 cat -A 则 [tab] 会以 ^I 来表示。 但经过 col -x 的处理,则会将 [tab] 取代成为对等的空白键!此外, col 经常被利用于将 man page 转存为纯文字档以方便查阅的功能!如上述的範例二!

  join

  join 看字面上的意义 (加入/参加) 就可以知道,他是在处理两个档案之间的资料, 而且,主要是在处理『两个档案当中,有 "相同资料" 的那一行,才将他加在一起』的意思。我们利用底下的简单例子来说明:

  [root@www ~]# join [-ti12] file1 file2

  选项与参数:

  -t :join 预设以空白字元分隔资料,并且比对『第一个栏位』的资料,

  如果两个档案相同,则将两笔资料联成一行,且第一个栏位放在第一个!

  -i :忽略大小写的差异;

  -1 :这个是数字的 1 ,代表『第一个档案要用那个栏位来分析』的意思;

  -2 :代表『第二个档案要用那个栏位来分析』的意思。

  範例一:用 root 的身份,将 /etc/passwd 与 /etc/shadow 相关资料整合成一栏

  [root@www ~]# head -n 3 /etc/passwd /etc/shadow

  ==> /etc/passwd <==

  root:x:0:0:root:/root:/bin/bash

  bin:x:1:1:bin:/bin:/sbin/nologin

  daemon:x:2:2:daemon:/sbin:/sbin/nologin

  ==> /etc/shadow <==

  root:$1$/3AQpE5e$y9A/D0bh6rElAs:14120:0:99999:7:::

  bin:*:14126:0:99999:7:::

  daemon:*:14126:0:99999:7:::

  # 由输出的资料可以发现这两个档案的最左边栏位都是帐号!且以 : 分隔

  [root@www ~]# join -t ':' /etc/passwd /etc/shadow

  root:x:0:0:root:/root:/bin/bash:$1$/3AQpE5e$y9A/D0bh6rElAs:14120:0:99999:7:::

  bin:x:1:1:bin:/bin:/sbin/nologin:*:14126:0:99999:7:::

  daemon:x:2:2:daemon:/sbin:/sbin/nologin:*:14126:0:99999:7:::

  # 透过上面这个动作,我们可以将两个档案第一栏位相同者整合成一行!

  # 第二个档案的相同栏位并不会显示(因为已经在第一行了嘛!)

  範例二:我们知道 /etc/passwd 第四个栏位是 GID ,那个 GID 记录在

  /etc/group 当中的第叁个栏位,请问如何将两个档案整合?

  [root@www ~]# head -n 3 /etc/passwd /etc/group

  ==> /etc/passwd <==

  root:x:0:0:root:/root:/bin/bash

  bin:x:1:1:bin:/bin:/sbin/nologin

  daemon:x:2:2:daemon:/sbin:/sbin/nologin

  ==> /etc/group <==

  root:x:0:root

  bin:x:1:root,bin,daemon

  daemon:x:2:root,bin,daemon

  # 从上面可以看到,确实有相同的部分喔!赶紧来整合一下!,网站建设

  [root@www ~]# join -t ':' -1 4 /etc/passwd -2 3 /etc/group

  0:root:x:0:root:/root:/bin/bash:root:x:root

  1:bin:x:1:bin:/bin:/sbin/nologin:bin:x:root,bin,daemon

  2:daemon:x:2:daemon:/sbin:/sbin/nologin:daemon:x:root,bin,daemon

  # 同样的,相同的栏位部分被移动到最前面了!所以第二个档案的内容就没再显示。

  # 请读者们配合上述显示两个档案的实际内容来比对!

  这个 join 在处理两个相关的资料档案时,就真的是很有帮助的啦! 例如上面的案例当中,我的 /etc/passwd, /etc/shadow, /etc/group 都是有相关性的, 其中 /etc/passwd, /etc/shadow 以帐号为相关性,至于 /etc/passwd, /etc/group 则以所谓的 GID (帐号的数字定义) 来作为他的相关性。根据这个相关性, 我们可以将有关係的资料放置在一起!这在处理资料可是相当有帮助的! 但是上面的例子有点难,希望您可以静下心好好的看一看塬因喔!

  此外,需要特别注意的是,在使用 join 之前,你所需要处理的档案应该要事先经过排序 (sort) 处理! 否则有些比对的项目会被略过呢!特别注意了!

  paste

  这个 paste 就要比 join 简单多了!相对于 join 必须要比对两个档案的资料相关性, paste 就直接『将两行贴在一起,且中间以 [tab] 键隔开』而已!简单的使用方法:

  [root@www ~]# paste [-d] file1 file2

  选项与参数:

  -d :后面可以接分隔字元。预设是以 [tab] 来分隔的!

  - :如果 file 部分写成 - ,表示来自 standard input 的资料的意思。

  範例一:将 /etc/passwd 与 /etc/shadow 同一行贴在一起

  [root@www ~]# paste /etc/passwd /etc/shadow

  bin:x:1:1:bin:/bin:/sbin/nologin bin:*:14126:0:99999:7:::

  daemon:x:2:2:daemon:/sbin:/sbin/nologin daemon:*:14126:0:99999:7:::

  adm:x:3:4:adm:/var/adm:/sbin/nologin adm:*:14126:0:99999:7:::

  # 注意喔!同一行中间是以 [tab] 按键隔开的!

  範例二:先将 /etc/group 读出(用 cat),然后与範例一贴上一起!且仅取出前叁行

  [root@www ~]# cat /etc/group|paste /etc/passwd /etc/shadow -|head -n 3

  # 这个例子的重点在那个 - 的使用!那玩意儿常常代表 stdin 喔!

  expand

  这玩意儿就是在将 [tab] 按键转成空白键啦~可以这样玩:

  [root@www ~]# expand [-t] file

  选项与参数:

  -t :后面可以接数字。一般来说,一个 tab 按键可以用 8 个空白键取代。

  我们也可以自行定义一个 [tab] 按键代表多少个字元呢!

  範例一:将 /etc/man.config 内行首为 MANPATH 的字样就取出;仅取前叁行;

  [root@www ~]# grep '^MANPATH' /etc/man.config | head -n 3

  MANPATH /usr/man

  MANPATH /usr/share/man

  MANPATH /usr/local/man

  # 行首的代表标誌为 ^ ,这个我们留待下节介绍!先有概念即可!

  範例二:承上,如果我想要将所有的符号都列出来?(用 cat)

  [root@www ~]# grep '^MANPATH' /etc/man.config | head -n 3 |cat -A

  MANPATH^I/usr/man$

  MANPATH^I/usr/share/man$

  MANPATH^I/usr/local/man$

  # 发现差别了吗?没错~ [tab] 按键可以被 cat -A 显示成为 ^I

  範例叁:承上,我将 [tab] 按键设定成 6 个字元的话?

  [root@www ~]# grep '^MANPATH' /etc/man.config | head -n 3 | \

  > expand -t 6 - | cat -A

  MANPATH /usr/man$

  MANPATH /usr/share/man$

  MANPATH /usr/local/man$

  123456123456123456.....

  # 仔细看一下上面的数字说明,因为我是以 6 个字元来代表一个 [tab] 的长度,所以,

  # MAN... 到 /usr 之间会隔 12 (两个 [tab]) 个字元喔!如果 tab 改成 9 的话,企业邮箱

  # 情况就又不同了!这裡也不好理解~您可以多设定几个数字来查阅就晓得!

  expand 也是挺好玩的~他会自动将 [tab] 转成空白键~所以,以上面的例子来说, 使用 cat -A 就会查不到 ^I 的字符啰~此外,因为 [tab] 最大的功能就是格式排列整齐! 我们转成空白键后,这个空白键也会依据我们自己的定义来增加大小~ 所以,并不是一个 ^I 就会换成 8 个空白喔!这个地方要特别注意的哩! 此外,您也可以参考一下 unexpand 这个将空白转成 [tab] 的指令功能啊! ^_^

  分割命令: split

  如果你有档案太大,导致一些携带式装置无法复製的问题,嘿嘿!找 split 就对了! 他可以帮你将一个大档案,依据档案大小或行数来分割,就可以将大档案分割成为小档案了! 快速又有效啊!真不错~

  [root@www ~]# split [-bl] file PREFIX

  选项与参数:

  -b :后面可接欲分割成的档案大小,可加单位,例如 b, k, m 等;

  -l :以行数来进行分割。

  PREFIX :代表前置字元的意思,可作为分割档案的前导文字。

  範例一:我的 /etc/termcap 有七百多K,若想要分成 300K 一个档案时?

  [root@www ~]# cd /tmp; split -b 300k /etc/termcap termcap

  [root@www tmp]# ll -k termcap*

  -rw-r--r-- 1 root root 300 Feb 7 16:39 termcapaa

  -rw-r--r-- 1 root root 300 Feb 7 16:39 termcapab

  -rw-r--r-- 1 root root 189 Feb 7 16:39 termcapac

  # 那个档名可以随意取的啦!我们只要写上前导文字,小档案就会以

  # xxxaa, xxxab, xxxac 等方式来建立小档案的!

  範例二:如何将上面的叁个小档案合成一个档案,档名为 termcapback

  [root@www tmp]# cat termcap* >> termcapback

  # 很简单吧?就用资料流重导向就好啦!简单!

  範例叁:使用 ls -al / 输出的资讯中,每十行记录成一个档案

  [root@www tmp]# ls -al / | split -l 10 - lsroot

  [root@www tmp]# wc -l lsroot*

  10 lsrootaa

  10 lsrootab

  6 lsrootac

  26 total

  # 重点在那个 - 啦!一般来说,如果需要 stdout/stdin 时,但偏偏又没有档案,

  # 有的只是 - 时,那么那个 - 就会被当成 stdin 或 stdout ~

  在 Windows 作业系统下,你要将档案分割需要如何作?伤脑筋吧!在 Linux 底下就简单的多了!你要将档案分割的话,那么就使用 -b size 来将一个分割的档案限制其大小,如果是行数的话,那么就使用 -l line 来分割!好用的很!如此一来,你就可以轻易的将你的档案分割成软碟 (floppy) 的大小,方便你 copy 啰!

  参数代换: xargs

  xargs 是在做什么的呢?就以字面上的意义来看, x 是加减乘除的乘号,args 则是 arguments (参数) 的意思,所以说,这个玩意儿就是在产生某个指令的参数的意思! xargs 可以读入 stdin 的资料,并且以空白字元或断行字元作为分辨,将 stdin 的资料分隔成为 arguments 。 因为是以空白字元作为分隔,所以,如果有一些档名或者是其他意义的名词内含有空白字元的时候, xargs 可能就会误判了~他的用法其实也还满简单的!就来看一看先!

  [root@www ~]# xargs [-0epn] command

  选项与参数:

  -0 :如果输入的 stdin 含有特殊字元,例如 `, \, 空白键等等字元时,这个 -0 参数

  可以将他还塬成一般字元。这个参数可以用于特殊状态喔!

  -e :这个是 EOF (end of file) 的意思。后面可以接一个字串,当 xargs 分析到

  这个字串时,就会停止继续工作!

  -p :在执行每个指令的 argument 时,都会询问使用者的意思;

  -n :后面接次数,每次 command 指令执行时,要使用几个参数的意思。看範例叁。

  当 xargs 后面没有接任何的指令时,预设是以 echo 来进行输出喔!

  範例一:将 /etc/passwd 内的第一栏取出,仅取叁行,使用 finger 这个指令将每个

  帐号内容秀出来

  [root@www ~]# cut -d':' -f1 /etc/passwd |head -n 3| xargs finger

  Login: root Name: root

  Directory: /root Shell: /bin/bash

  Never logged in.

  No mail.

  No Plan.

  ......底下省略.....

  # 由 finger account 可以取得该帐号的相关说明内容,例如上面的输出就是 finger root

  # 后的结果。在这个例子当中,我们利用 cut 取出帐号名称,用 head 取出叁个帐号,

  # 最后则是由 xargs 将叁个帐号的名称变成 finger 后面需要的参数!

  範例二:同上,但是每次执行 finger 时,都要询问使用者是否动作?

  [root@www ~]# cut -d':' -f1 /etc/passwd |head -n 3| xargs -p finger

  finger root bin daemon ?...y

  .....(底下省略)....

  # 嗬嗬!这个 -p 的选项可以让使用者的使用过程中,被询问到每个指令是否执行!

  範例叁:将所有的 /etc/passwd 内的帐号都以 finger 查阅,但一次仅查阅五个帐号

  [root@www ~]# cut -d':' -f1 /etc/passwd | xargs -p -n 5 finger

  finger root bin daemon adm lp ?...y

  .....(中间省略)....

  finger uucp operator games gopher ftp ?...y

  .....(底下省略)....

  # 在这裡鸟哥使用了 -p 这个参数来让您对于 -n 更有概念。一般来说,某些指令后面

  # 可以接的 arguments 是有限制的,不能无限制的累加,此时,我们可以利用 -n

  # 来帮助我们将参数分成数个部分,每个部分分别再以指令来执行!这样就 OK 啦!^_^

  範例四:同上,但是当分析到 lp 就结束这串指令?

  [root@www ~]# cut -d':' -f1 /etc/passwd | xargs -p -e'lp' finger

  finger root bin daemon adm ?...

  # 仔细与上面的案例做比较。也同时注意,那个 -e'lp' 是连在一起的,中间没有空白键。

  # 上个例子当中,第五个参数是 lp 啊,那么我们下达 -e'lp' 后,则分析到 lp

  # 这个字串时,后面的其他 stdin 的内容就会被 xargs 捨弃掉了!

  其实,在 man xargs 裡面就有叁四个小範例,您可以自行参考一下内容。 此外, xargs 真的是很好用的一个玩意儿!您真的需要好好的参详参详!会使用 xargs 的塬因是, 很多指令其实并不支援管线命令,因此我们可以透过 xargs 来提供该指令引用 standard input 之用!举例来说,我们使用如下的範例来说明:

  範例五:找出 /sbin 底下具有特殊权限的档名,并使用 ls -l 列出详细属性

  [root@www ~]# find /sbin -perm +7000 | ls -l

  # 结果竟然仅有列出 root 所在目录下的档案!这不是我们要的!

  # 因为 ll (ls) 并不是管线命令的塬因啊!

  [root@www ~]# find /sbin -perm +7000 | xargs ls -l

  -rwsr-xr-x 1 root root 70420 May 25 2008 /sbin/mount.nfs

  -rwsr-xr-x 1 root root 70424 May 25 2008 /sbin/mount.nfs4

  -rwxr-sr-x 1 root root 5920 Jun 15 2008 /sbin/netreport

  ....(底下省略)....

  关于减号 - 的用途

  管线命令在 bash 的连续的处理程序中是相当重要的!另外,在 log file 的分析当中也是相当重要的一环, 所以请特别留意!另外,在管线命令当中,常常会使用到前一个指令的 stdout 作为这次的 stdin , 某些指令需要用到档案名称 (例如 tar) 来进行处理时,该 stdin 与 stdout 可以利用减号 "-" 来替代, 举例来说:

  [root@www ~]# tar -cvf - /home | tar -xvf -

  上面这个例子是说:『我将 /home 裡面的档案给他打包,但打包的资料不是纪录到档案,而是传送到 stdout; 经过管线后,将 tar -cvf - /home 传送给后面的 tar -xvf - 』。后面的这个 - 则是取用前一个指令的 stdout, 因此,我们就不需要使用 file 了!这是很常见的例子喔!注意注意!


文章源自谷搜服务商 双向重导向: tee
  评论这张
 
阅读(13)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017