Chinaunix首页 | 论坛 | 博客

分类:

2009-01-17 14:10:53

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

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

[root@linux ~]# tr [-ds] SET1 ...
参数:
-d  :删除讯息当中的 SET1 这个字串;
-s  :取代掉重复的字元!
范例:

范例一:将 last 输出的讯息中,所有的小写变成大写字元:
[root@linux ~]# last | tr '[a-z]' '[A-Z]'

范例二:将 /etc/passwd 输出的讯息中,将冒号 (:) 删除
[root@linux ~]# cat /etc/passwd | tr -d ':'

范例三:将 DOS 档案的断行字元 ^M 符号删除:
[root@linux ~]# cat /home/test/dostxt | tr -d '\r' > dostxt-noM
# 那个 \r 指的是 DOS 的断行字元,关于更多的字符,请参考 man tr

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

# col

[root@linux ~]# col [-x]
参数:
-x  :将 tab 键转换成对等的空白键
范例:
[root@linux ~]# cat -A /etc/man.config  <==此时会看到很多 ^I 的符号,那就是 tab
[root@linux ~]# cat /etc/man.config | col -x | cat -A | more
# 嘿嘿!如此一来, [tab] 按键会被取代成为空白键,输出就美观多了!

虽然 col 有他特殊的用途,不过,很多时候,他可以用来简单的处理将 [tab] 按键取代成为空白键! 例如上面的例子当中,如果使用 cat -A 则 [tab] 会以 ^I 来表示。 但经过 col -x 的处理,则会将 [tab] 取代成为对等的空白键!

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

[root@linux ~]# join [-ti12] file1 file2
参数:
-t  :join 预设以空白字元分隔资料,并且比对‘第一个栏位’的资料,
      如果两个档案相同,则将两笔资料联成一行,且第一个栏位放在第一个!
-i  :忽略大小写的差异;
-1  :这个是数字的 1 ,代表‘第一个档案要用那个栏位来分析’的意思;
-2  :代表‘第二个档案要用那个栏位来分析’的意思。
范例:

范例一:用 root 的身份,将 /etc/passwd 与 /etc/shadow 相关资料整合成一栏
[root@linux ~]# join -t ':' /etc/passwd /etc/shadow
bin:x:1:1:bin:/bin:/sbin/nologin:*:12959:0:99999:7:::
daemon:x:2:2:daemon:/sbin:/sbin/nologin:*:12959:0:99999:7:::
adm:x:3:4:adm:/var/adm:/sbin/nologin:*:12959:0:99999:7:::
# 因为 /etc/shadow 的权限问题,所以这里必须是 root 才能动作!而 /etc/passwd
# 与 /etc/shadow 都是以 : 来分隔栏位,所以必须要使用 -t ':' 规范栏位分隔字元。
# 且,因为 /etc/shadow 与 /etc/passwd 刚好都是以第一个栏位为帐号名称,所以,
# 就可以将同一行的资料给他贴在一起了!
# 另外,再仔细看一下 /etc/shadow 的内容与 /etc/passwd 的内容,您会发现,
# 两者都以帐号为开始,而上面的输出资料中您会发现特殊字体部分,那代表
# 第二个档案的内容。在第二个档案的内容部分,由于帐号(第一个栏位)与
# 第一的档案是相同的,所以当然就省略掉,因此就成为上面的输出。

范例二:我们知道 /etc/passwd 第四个栏位是 GID ,那个 GID 记录在
        /etc/group 当中的第三个栏位,请问如何将两个档案整合?
[root@linux ~]# join -t ':' -1 4 /etc/passwd -2 3 /etc/group
0:root:x:0:root:/root:/bin/bash:root:x:
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
4:adm:x:3:adm:/var/adm:/sbin/nologin:adm:x:root,adm,daemon
# 这个例子就更明显了!原本的 /etc/passwd 的第一行内容应该是:
# root:x:0:0:root:/root:/bin/bash
# 至于 /etc/group 第一行内容应该是:
# root:x:0:
# 我将第一个档案的第四栏与第二个档案的第三栏取出,放置到输出的最前方,
# 然后将剩下的资料给他加在一起!就成了上面的输出啦!

这个 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@linux ~]# paste [-d] file1 file2
参数:
-d  :后面可以接分隔字元。预设是以 [tab] 来分隔的!
-   :如果 file 部分写成 - ,表示来自 standard input 的资料的意思。
范例:

范例一:将 /etc/passwd 与 /etc/shadow 同一行贴在一起
[root@linux ~]# paste /etc/passwd /etc/shadow
bin:x:1:1:bin:/bin:/sbin/nologin        bin:*:12959:0:99999:7:::
daemon:x:2:2:daemon:/sbin:/sbin/nologin daemon:*:12959:0:99999:7:::
adm:x:3:4:adm:/var/adm:/sbin/nologin    adm:*:12959:0:99999:7:::
# 注意喔!同一行中间是以 [tab] 按键隔开的!

范例二:先将 /etc/group 读出(用 cat),然后与范例一贴上一起!且仅取出前三行
[root@linux ~]# cat /etc/group|paste /etc/passwd /etc/shadow -|head -n 3
# 这个例子的重点在那个 - 的使用!那玩意儿常常代表 stdin 喔!


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

[root@linux ~]# expand [-t] file
参数:
-t  :后面可以接数字。一般来说,一个 tab 按键可以用 8 个空白键取代。
      我们也可以自行定义一个 [tab] 按键代表多少个字元呢!
范例:

范例一:将 /etc/man.config 内行首为 MANPATH 的字样就取出;仅取前三行;
[root@linux ~]# grep '^MANPATH' /etc/man.config | head -n 3
MANPATH /usr/man
MANPATH /usr/share/man
MANPATH /usr/local/man
# 行首的代表标志为 ^ ,这个我们留待下节介绍!先有概念即可!

范例二:承上,如果我想要将所有的符号都列出来?(用 cat)
[root@linux ~]# 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@linux ~]# 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] 的指令功能啊! ^_^
阅读(1232) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~