linux 管道命令指南

匿名 (未验证) 提交于 2019-12-02 21:59:42

cut

cut 不就是『切』吗?没错啦!这个指令可以将一段讯息的某一段给他『切』出来~ 处理的讯息是以『行』为单位喔!底下我们就来谈一谈:

[dmtsai@study ~]$ cut -d'分隔字元' -f fields  <==用于有特定分隔字元  [dmtsai@study ~]$ cut -c字元区间             <==用于排列整齐的讯息 选项与参数: -d :后面接分隔字元。与-f 一起使用; -f :依据-d 的分隔字元将一段讯息分割成为数段,用-f 取出第几段的意思; -c :以字元(characters) 的单位取出固定字元区间;  范例一:将PATH变数取出,我要找出第五个路径。 [dmtsai@study ~]$ echo ${PATH} /usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/dmtsai/.local/bin:/home/dmtsai/bin # 1           | 2      | 3             | 4       | 5                     | 6              |  [dmtsai@study ~]$ echo ${PATH} | cut -d ':' -f 5  #如同上面的数字显示,我们是以『 : 』作为分隔,因此会出现/home/dmtsai/.local/bin #那么如果想要列出第3与第5呢?,就是这样:  [dmtsai@study ~]$ echo ${PATH} | cut -d ':' -f 3,5  范例二:将export输出的讯息,取得第12字元以后的所有字串  [dmtsai@study ~]$ export declare -x HISTCONTROL="ignoredups" declare -x HISTSIZE="1000" declare -x HOME="/home/dmtsai" declare -x HOSTNAME="study.centos.vbird" .....(其他省略)..... # 注意看,每个资料都是排列整齐的输出!如果我们不想要『 declare -x 』时,就得这么做:  [dmtsai@study ~]$ export | cut -c 12- HISTCONTROL="ignoredups" HISTSIZE="1000" HOME="/home/dmtsai" HOSTNAME="study.centos.vbird" .....(其他省略)..... # 知道怎么回事了吧?用-c 可以处理比较具有格式的输出资料! # 我们还可以指定某个范围的值,例如第12-20 的字元,就是cut -c 12-20 等等!  范例三:用last将显示的登入者的资讯中,仅留下使用者大名  [dmtsai@study ~]$ last root pts/1 192.168.201.101 Sat Feb 7 12:35 still logged in root pts/1 192.168.201.101 Fri Feb 6 12:13 - 18:46 (06:33) root pts/1 192.168.201.254 Thu Feb 5 22:37 - 23:53 (01:16) # last 可以输出『帐号/终端机/来源/日期时间』的资料,并且是排列整齐的  [dmtsai@study ~]$ last | cut -d ' ' -f 1  #由输出的结果我们可以发现第一个空白分隔的栏位代表帐号,所以使用如上指令: # 但是因为root pts/1 之间空格有好几个,并非仅有一个,所以,如果要找出  # pts/1 其实不能以cut -d ' ' -f 1,2 喔!输出的结果会不是我们想要的。

cut 主要的用途在于将『同一行里面的资料进行分解!』最常使用在分析一些数据或文字资料的时候!这是因为有时候我们会以某些字元当作分割的参数,然后来将资料加以切割,以取得我们所需要的资料。不过,cut 在处理多空格相连的资料时,可能会比较吃力一点,所以某些时刻可能会使用下一章的awk 来取代的!

grep

刚刚的cut 是将一行讯息当中,取出某部分我们想要的,而grep 则是分析一行讯息, 若当中有我们所需要的资讯,就将该行拿出来~简单的语法是这样的:

grep 是个很棒的指令喔!他支援的语法实在是太多了~用在正规表示法里头, 能够处理的资料实在是多的很~ grep 可以解析一行文字,取得关键字,若该行有存在关键字,就会整行列出来!

sort

sort 同样是很常用的指令呢!因为我们常常需要比较一些信息啦!举个上面的第二个例子来说好了!今天假设你有很多的帐号,而且你想要知道最大的使用者 ID 目前到哪一号了!呵呵!使用sort 一下子就可以知道答案咯!

uniq

如果我排序完成了,想要将重复的资料仅列出一个显示,可以怎么做呢?

[dmtsai@study ~]$ uniq [-ic]  选项与参数: -i :忽略大小写字元的不同; -c :进行计数  范例一:使用last将帐号列出,仅取出帐号栏,进行排序后仅取出一位;  [dmtsai@study ~]$ last | cut -d ' ' -f1 | sort | uniq  范例二:承上题,如果我还想要知道每个人的登入总次数呢? [dmtsai@study ~]$ last | cut -d ' ' -f1 | sort | uniq -c       1       6 (unknown      47 dmtsai       4 reboot       7 root       1 wtmp # 从上面的结果可以发现reboot 有4 次, root 登入则有7 次!大部分是以dmtsai 来操作! # wtmp 与第一行的空白都是last 的预设字元,那两个可以忽略的!

wc

如果我想要知道/etc/man_db.conf 这个档案里面有多少字?多少行?多少字元的话, 可以怎么做呢?其实可以利用wc 这个指令来达成喔!他可以帮我们计算输出的讯息的整体资料!

当你要知道目前你的帐号档案中有多少个帐号时,就使用这个方法:cat /etc/passwd | wc -l 啦!因为/etc/passwd 里头一行代表一个使用者呀!所以知道行数就晓得有多少的帐号在里头了!而如果要计算一个档案里头有多少个字元时,就使用 wc -m 这个选项吧!

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

[dmtsai@study ~]$ tee [-a] file  选项与参数: -a :以累加(append) 的方式,将资料加入file 当中!  [dmtsai@study ~]$ last | tee last.list | cut -d " " -f1  #这个范例可以让我们将last的输出存一份到last.list档案中;  [dmtsai@study ~]$ ls -l /home | tee ~/homefile | more  #这个范例则是将ls的资料存一份到~/homefile ,同时萤幕也有输出讯息!  [dmtsai@study ~]$ ls -l / | tee -a ~/homefile | more  #要注意!tee后接的档案会被覆盖,若加上-a这个选项则能将讯息累加。

tee 可以让standard output 转存一份到档案内并将同样的资料继续送到萤幕去处理!这样除了可以让我们同时分析一份资料并记录下来之外,还可以作为处理一份资料的中间暂存档记录之用!

tr

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

[dmtsai@study ~]$ tr [-ds] SET1 ...  选项与参数: -d :删除讯息当中的SET1 这个字串; -s :取代掉重复的字元!  范例一:将last输出的讯息中,所有的小写变成大写字元:  [dmtsai@study ~]$ last | tr '[az]' '[AZ]'  #事实上,没有加上单引号也是可以执行的,如:『 last | tr [az] [AZ] 』  范例二:将/etc/passwd输出的讯息中,将冒号(:)删除  [dmtsai@study ~]$ cat /etc/passwd | tr -d ':'  范例三:将/etc/passwd转存成dos断行到/root/passwd中,再将^M符号删除  [dmtsai@study ~]$ cp /etc/passwd ~/passwd && unix2dos ~/passwd  [dmtsai@ study ~]$ file /etc/passwd ~/passwd /etc/passwd: ASCII text /home/dmtsai/passwd: ASCII text, with CRLF line terminators   <==就是DOS断行  [dmtsai@study ~]$ cat ~/passwd | tr -d '\r' > ~/passwd.linux  #那个\r指的是DOS的断行字元,关于更多的字符,请参考man tr  [dmtsai@study ~]$ ll /etc/passwd ~/passwd*  -rw-r--r--. 1 root root    2092 Jun 17 00:20 /etc/passwd -rw-r--r--. 1 dmtsai dmtsai 2133 Jul 9 22:13 /home/dmtsai/passwd -rw-rw-r--. 1 dmtsai dmtsai 2092 Jul 9 22:13 /home/dmtsai/passwd.linux  #处理过后,发现档案大小与原本的/etc/passwd就一致了!

col

[dmtsai@study ~]$ col [-xb]  选项与参数: -x :将tab 键转换成对等的空白键  范例一:利用cat -A显示出所有特殊按键,最后以col将[tab]转成空白  [dmtsai@study ~]$ cat -A /etc/man_db.conf   <==此时会看到很多^I的符号,那就是tab  [dmtsai@study ~]$ cat /etc/man_db.conf | col -x | cat -A | more  #嘿嘿!如此一来, [tab]按键会被取代成为空白键,输出就美观多了!

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

join

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

[dmtsai@study ~]$ join [-ti12] file1 file2  选项与参数: -t :join 预设以空白字元分隔资料,并且比对『第一个栏位』的资料,       如果两个档案相同,则将两笔资料联成一行,且第一个栏位放在第一个! -i :忽略大小写的差异; -1 :这个是数字的1 ,代表『第一个档案要用那个栏位来分析』的意思; -2 :代表『第二个档案要用那个栏位来分析』的意思。  范例一:用root的身份,将/etc/passwd与/etc/shadow相关资料整合成一栏  [root@study ~]# 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:$6$wtbCCce/PxMeE5wm$KE2IfSJr...:16559:0:99999:7::: bin:*:16372:0:99999:7::: daemon:*:16372:0:99999:7::: # 由输出的资料可以发现这两个档案的最左边栏位都是相同帐号!且以: 分隔  [root@study ~]# join -t ':' /etc/passwd /etc/shadow | head -n 3  root :x:0:0:root:/root:/bin/bash: $6$wtbCCce/PxMeE5wm$ KE2IfSJr...:16559:0:99999:7:::  bin :x:1:1:bin:/bin:/sbin/nologin: *:16372:0:99999:7:::  daemon :x:2 :2:daemon:/sbin:/sbin/nologin: *:16372:0:99999:7:::  #透过上面这个动作,我们可以将两个档案第一栏位相同者整合成一列! # 第二个档案的相同栏位并不会显示(因为已经在最左边的栏位出现了啊!)  范例二:我们知道/etc/passwd 第四个栏位是GID ,那个GID 记录在          /etc/group当中的第三个栏位,请问如何将两个档案整合? [root@study ~]# 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 : bin:x: 1 : daemon:x: 2 :  #从上面可以看到,确实有相同的部分喔!赶紧来整合一下!  [root@study ~]# join -t ':' -1 4 /etc/passwd -2 3 /etc/group | head -n 3  0 :root:x:0:root:/root:/bin/bash: root:x:  1 :bin:x:1:bin:/bin:/sbin/nologin: bin:x:  2 :daemon:x:2:daemon:/sbin:/sbin/nologin: daemon:x:  #同样的,相同的栏位部分被移动到最前面了!所以第二个档案的内容就没再显示。 # 请读者们配合上述显示两个档案的实际内容来比对!

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

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

paste

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

[dmtsai@study ~]$ paste [-d] file1 file2  选项与参数: -d :后面可以接分隔字元。预设是以[tab] 来分隔的! - :如果file 部分写成- ,表示来自standard input 的资料的意思。  范例一:用root身份,将/etc/passwd与/etc/shadow同一行贴在一起  [root@study ~]# paste /etc/passwd /etc/shadow  root : x : 0:0 : root:/root :/bin/bash root:$6$wtbCCce/PxMeE5wm$KE2IfSJr...:16559:0:99999:7::: bin:x:1:1:bin:/bin:/sbin/nologin bin:*:16372:0:99999:7::: daemon:x:2:2:daemon:/sbin:/sbin/nologin daemon:*:16372:0:99999:7::: # 注意喔!同一行中间是以[tab] 按键隔开的!  范例二:先将/etc/group读出(用cat),然后与范例一贴上一起!且仅取出前三行  [root@study ~]# cat /etc/group|paste /etc/passwd /etc/shadow -|head -n 3  #这个例子的重点在那个-的使用!那玩意儿常常代表stdin喔!

expand

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

[dmtsai@study ~]$ expand [-t] file  选项与参数: -t :后面可以接数字。一般来说,一个tab 按键可以用8 个空白键取代。       我们也可以自行定义一个[tab] 按键代表多少个字元呢!  范例一:将/etc/man_db.conf内行首为MANPATH的字样就取出;仅取前三行;  [dmtsai@study ~]$ grep '^MANPATH' /etc/man_db.conf | head -n 3 MANPATH_MAP /bin /usr/share/man MANPATH_MAP /usr/bin /usr/share/man MANPATH_MAP /sbin /usr/share/man # 行首的代表标志为^ ,这个我们留待下节介绍!先有概念即可!  范例二:承上,如果我想要将所有的符号都列出来?(用cat)  [dmtsai@study ~]$ grep '^MANPATH' /etc/man_db.conf | head -n 3 |cat -A MANPATH_MAP^I/bin^I^I^I/usr/share/man$ MANPATH_MAP^I/usr/bin^I^I/usr/share/man$ MANPATH_MAP^I/sbin^I^I^I/usr/share/man$ # 发现差别了吗?没错~ [tab] 按键可以被cat -A 显示成为^I  范例三:承上,我将[tab]按键设定成6个字元的话? [dmtsai@study ~]$ grep '^MANPATH' /etc/man_db.conf | head -n 3 | expand -t 6 - | cat -A MANPATH_MAP /bin /usr/share/man$ MANPATH_MAP /usr/bin /usr/share/man$ MANPATH_MAP /sbin /usr/share/man$ 123456123456123456123456123456123456123456123456... # 仔细看一下上面的数字说明,因为我是以6 个字元来代表一个[tab] 的长度,所以, # MAN... 到/usr 之间会隔12 (两个[tab]) 个字元喔!如果tab 改成9 的话, # 情况就又不同了!这里也不好理解~您可以多设定几个数字来查阅就晓得!

split

他可以帮你将一个大档案,依据档案大小或行数来分割,就可以将大档案分割成为小档案了!快速又有效啊!真不错~

[dmtsai@study ~]$ split [-bl] file PREFIX  选项与参数: -b :后面可接欲分割成的档案大小,可加单位,例如b, k, m 等; -l :以行数来进行分割。 PREFIX :代表前置字元的意思,可作为分割档案的前导文字。  范例一:我的/etc/services有六百多K,若想要分成300K一个档案时? [dmtsai@study ~]$ cd /tmp; split -b 300k /etc/services services  [dmtsai@study tmp]$ ll -k services*  -rw-rw-r--. 1 dmtsai dmtsai 307200 Jul 9 22:52 services aa  -rw-rw-r--. 1 dmtsai dmtsai 307200 Jul 9 22:52 services ab  -rw-rw-r--. 1 dmtsai dmtsai 55893 Jul 9 22:52 services ac  #那个档名可以随意取的啦!我们只要写上前导文字,小档案就会以 # xxxaa, xxxab, xxxac 等方式来建立小档案的!  范例二:如何将上面的三个小档案合成一个档案,档名为servicesback  [dmtsai@study tmp]$ cat services* >> servicesback  #很简单吧?就用资料流重导向就好啦!简单!  范例三:使用ls -al /输出的资讯中,每十行记录成一个档案  [dmtsai@study tmp]$ ls -al / | split -l 10 - lsroot  [dmtsai@study tmp]$ wc -l lsroot*   10 lsrootaa   10 lsrootab    4 lsrootac   24 total # 重点在那个- 啦!一般来说,如果需要stdout/stdin 时,但偏偏又没有档案, # 有的只是- 时,那么那个- 就会被当成stdin 或stdout ~

xargs

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

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

范例四:找出/usr/sbin底下具有特殊权限的档名,并使用ls -l列出详细属性  [dmtsai@study ~]$ find /usr/sbin -perm /7000 | xargs ls -l -rwx--s--x. 1 root lock 11208 Jun 10 2014 /usr/sbin/lockdev -rwsr-xr-x. 1 root root 113400 Mar 6 12:17 /usr/sbin/mount.nfs -rwxr-sr-x. 1 root root 11208 Mar 6 11:05 /usr/sbin/netreport .....(底下省略)..... # 聪明的读者应该会想到使用『 ls -l $(find /usr/sbin -perm /7000) 』来处理这个范例! # 都OK!能解决问题的方法,就是好方法!

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

[root@study ~]# mkdir /tmp/homeback  [root@study ~]# tar -cvf - /home | tar -xvf - -C /tmp/homeback

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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!