linux 管道命令指南

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 则是分析一行讯息, 若当中有我们所需要的资讯,就将该行拿出来~简单的语法是这样的:

[dmtsai@study ~]$ grep [-acinv] [--color=auto] '搜寻字串' filename 
选项与参数:
-a :将binary 档案以text 档案的方式搜寻资料
-c :计算找到'搜寻字串' 的次数
-i :忽略大小写的不同,所以大小写视为相同
-n :顺便输出行号
-v :反向选择,亦即显示出没有'搜寻字串' 内容的那一行!
--color=auto :可以将找到的关键字部分加上颜色的显示喔!

范例一:将last当中,有出现root的那一行就取出来; 
[dmtsai@study ~]$ last | grep 'root'

范例二:与范例一相反,只要没有root的就取出!
[dmtsai@study ~]$ last | grep -v 'root'

范例三:在last的输出讯息中,只要有root就取出,并且仅取第一栏 
[dmtsai@study ~]$ last | grep 'root' |cut -d ' ' -f1 
#在取出root之后,利用上个指令cut的处理,就能够仅取得第一栏啰!

范例四:取出/etc/man_db.conf内含MANPATH的那几行 
[dmtsai@study ~]$ grep --color=auto 'MANPATH' /etc/man_db.conf 
....(前面省略)... . 
MANPATH _MAP /usr/games /usr/share/man
 MANPATH _MAP /opt/bin /opt/man
 MANPATH _MAP /opt/sbin /opt/man
 #神奇的是,如果加上--color=auto的选项,找到的关键字部分会用特殊颜色显示喔!

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

sort

[dmtsai@study ~]$ sort [-fbMnrtuk] [file or stdin] 
选项与参数:
-f :忽略大小写的差异,例如A 与a 视为编码相同;
-b :忽略最前面的空白字元部分;
-M :以月份的名字来排序,例如JAN, DEC 等等的排序方法;
-n :使用『纯数字』进行排序(预设是以文字型态来排序的);
-r :反向排序;
-u :就是uniq ,相同的资料中,仅出现一行代表;
-t :分隔符号,预设是用[tab] 键来分隔;
-k :以那个区间(field) 来进行排序的意思

范例一:个人帐号都记录在/etc/passwd下,请将帐号进行排序。
[dmtsai@study ~]$ cat /etc/passwd | sort 
ab rt:x:173:173::/etc/abrt:/sbin/nologin
 ad m:x:3:4:adm:/var/adm:/ sbin/nologin
 al ex:x:1001:1002::/home/alex:/bin/bash
 #鸟哥省略很多的输出~由上面的资料看起来, sort是预设『以第一个』资料来排序,
# 而且预设是以『文字』型态来排序的喔!所以由a 开始排到最后啰!

范例二:/etc/passwd内容是以:来分隔的,我想以第三栏含后面资料来排序,该如何?
[dmtsai@study ~]$ cat /etc/passwd | sort -t ':' -k 3 
root:x: 0:0:root:/root:/bin/bash 
dmtsai:x: 1000:1000:dmtsai:/ home/dmtsai:/bin/bash 
alex:x: 1001:1002::/home/alex:/bin/bash 
arod:x: 1002:1003::/home/arod:/bin/bash 
#看到特殊字体的输出部分了吧?怎么会这样排列啊?呵呵!没错啦~若单纯以第三栏位来处理则是:

[dmtsai@study ~]$ cat /etc/passwd | sort -t ':' -k 3,3
# 如果是以文字型态来排序的话,原本就会是这样,想要使用数字排序:
# cat /etc/passwd | sort -t ':' -k 3,3 -n
# 这样才行啊!用那个-n 来告知sort 以数字来排序啊!

范例三:利用last ,将输出的资料仅取帐号,并加以排序 
[dmtsai@study ~]$ last | cut -d ' ' -f1 | 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 的预设字元,那两个可以忽略的!

这个指令用来将『重复的行删除掉只显示一个』,举个例子来说, 你要知道这个月份登入你主机的使用者有谁,而不在乎他的登入次数,那么就使用上面的范例, (1)先将所有的资料列出;(2)再将人名独立出来;(3)经过排序;(4)只显示一个!由于这个指令是在将重复的东西减少,所以当然需要『配合排序过的档案』来处理啰!

wc

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

[dmtsai@study ~]$ wc [-lwm] 
选项与参数:
-l :仅列出行;
-w :仅列出多少字(英文单字);
-m :多少字元;

范例一:那个/etc/man_db.conf里面到底有多少相关字、行、字元数?
[dmtsai@study ~]$ cat /etc/man_db.conf | wc
    131 723 5171
# 输出的三个数字中,分别代表: 『行、字数、字元数』

范例二:我知道使用last 可以输出登入者,但是last 最后两行并非帐号内容,那么请问,
        我该如何以一行指令串取得登入系统的总人次?
[dmtsai@study ~]$ last | grep [a-zA-Z] | grep -v 'wtmp' | grep -v 'reboot' | \ 
> grep -v 'unknown' |wc -l 
#由于last会输出空白行, wtmp, unknown, reboot等无关帐号登入的资讯,因此,我利用
# grep 取出非空白行,以及去除上述关键字那几行,再计算行数,就能够了解啰!

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

双向重导向: tee

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

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 的话,
# 情况就又不同了!这里也不好理解~您可以多设定几个数字来查阅就晓得!

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

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 ~

在Windows 作业系统下,你要将档案分割需要如何作?伤脑筋吧!在Linux 底下就简单的多了!你要将档案分割的话,那么就使用-b size 来将一个分割的档案限制其大小,如果是行数的话,那么就使用 -l line 来分割!好用的很!如此一来,你就可以轻易的将你的档案分割成某些软体能够支援的最大容量(例如gmail 单一信件25MB 之类的!),方便你copy 啰!

xargs

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

[dmtsai@study ~]$ xargs [-0epn] command 
选项与参数:
-0 :如果输入的stdin 含有特殊字元,例如`, \, 空白键等等字元时,这个-0 参数
      可以将他还原成一般字元。这个参数可以用于特殊状态喔!
-e :这个是EOF (end of file) 的意思。后面可以接一个字串,当xargs 分析到这个字串时,
      就会停止继续工作!
-p :在执行每个指令的argument 时,都会询问使用者的意思;
-n :后面接次数,每次command 指令执行时,要使用几个参数的意思。
当xargs 后面没有接任何的指令时,预设是以echo 来进行输出喔!

范例一:将/etc/passwd内的第一栏取出,仅取三行,使用id这个指令将每个帐号内容秀出来 
[dmtsai@study ~]$ id root 
uid=0(root) gid=0( root) groups=0(root)    #这个id指令可以查询使用者的UID/GID等资讯

[dmtsai@study ~]$ id $(cut -d ':' -f 1 /etc/passwd | head -n 3) 
#虽然使用$(cmd)可以预先取得参数,但可惜的是, id这个指令『仅』能接受一个参数而已!
# 所以上述的这个指令执行会出现错误!根本不会显示用户的ID 啊!

[dmtsai@study ~]$ cut -d ':' -f 1 /etc/passwd | head -n 3 | id 
uid=1000(dmtsai) gid=1000(dmtsai) groups=1000(dmtsai),10(wheel)    #我不是要查自己啊!
#因为id并不是管线命令,因此在上面这个指令执行后,前面的东西通通不见!只会执行id!

[dmtsai@study ~]$ cut -d ':' -f 1 /etc/passwd | head -n 3 | xargs id 
#依旧会出现错误!这是因为xargs一口气将全部的资料通通丢给id处理~但id就接受1个啊最多!

[dmtsai@study ~]$ cut -d ':' -f 1 /etc/passwd | head -n 3 | xargs -n 1 id
uid=0(root) gid=0(root) groups=0(root)
uid=1(bin) gid=1(bin) groups=1(bin)
uid=2(daemon) gid=2(daemon) groups=2(daemon)
# 透过-n 来处理,一次给予一个参数,因此上述的结果就OK 正常的显示啰!

范例二:同上,但是每次执行id时,都要询问使用者是否动作?
[dmtsai@study ~]$ cut -d ':' -f 1 /etc/passwd | head -n 3 | xargs -p -n 1 id 
id root ?... y
uid=0(root) gid=0(root) groups=0(root)
id bin ?... y 
.....(底下省略).....
# 呵呵!这个-p 的选项可以让使用者的使用过程中,被询问到每个指令是否执行!

范例三:将所有的/etc/passwd内的帐号都以id查阅,但查到sync就结束指令串 
[dmtsai@study ~]$ cut -d ':' -f 1 /etc/passwd | xargs -e 'sync' -n 1 id 
#仔细与上面的案例做比较。也同时注意,那个-e'sync'是连在一起的,中间没有空白键。
# 上个例子当中,第六个参数是sync 啊,那么我们下达-e'sync' 后,则分析到sync 这个字串时,
# 后面的其他stdin 的内容就会被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 了!这是很常见的例子喔!注意注意!

你可能感兴趣的:(linux)