管道(pipe)
回到顶部
管道(pipe)命令是使用管道线符号|分割的命令。一条命令的输入可能来自标准输入或者文件,也可以来自另一条命令的输入。
同理,一条命令的输出可以输出到标准(错误)输出或者文件,也可以输出到另一条命令。管道就是将命令的标准输入重定向到另一条命令的标准输出,
命令的标准输出重定向到另一条命令的标准输入。这里要注意管道并不处理标准错误输出。管道线符号和重定向符号都属于数据重定向符号。
到目前为止,可以连接两条命令的符号有:
1.管道线;
2.重定向;
3.连续执行命令分号;
4.&&和||;
注意管掉线|和其他几个符号的区别。
我们先举一个简单的管道线命令,在用ls命令查看/etc目录下的文件的时候,由于/etc目录下的文件过多,超过了一屏,
导致前面的内容来不及看到。这时我们就可以将ls的输出通过管道线重定向到less命令,再由less命令输出到屏幕:
[peter@study ~]$ ls -al /etc | less这样ls命令的输出就被less命令读取,利用less的功能,就可以前后翻页查看相关的信息了! 管道命令|仅能处理命令的标准输入standard input和标准输出standard output, 对于standard error并没有直接处理的能力。管道命令示意如下图所示:
图 管道命令的处理示意图
通常重定向符号后面接的是文件,而管道后面接的必须是命令,而且这个命令必须能够接受standard input, 这样的命令才可以称为管道命令,例如less, more, head, tail等都是可以接受standard input的管道命令。 至于ls, cp, mv等就不是管道命令了!因为ls, cp, mv并不会接受来自stdin的数据。 综上所述,管道命令主要有两个需要注意的地方:
管道命令仅处理standard output,对于standard error output会予以忽略;
管道命令必须要能够接受来自前一个命令的数据成为standard input继续处理才行。
其实我们也可以将标准错误输出通过管道命令输入给管道命令, 只不过需要先将标准错误输出用重定向符号重定向到标准输出,即在管道线之前加入2>&1
下面介绍一些常用的管道命令。
常见的管道命令
回到顶部
常用管道命令
1.linux
cut命令
2.linux
grep命令
3.linux
tee命令
4.linux
wc命令
5.linux
join命令
6.linux
col命令
7.linux
expand命令
8.linux
paste命令
9.linux
sort命令
10.linux
split命令
11.linux
tr命令
12.linux
uniq命令
13.linux
xargs命令
提取命令: cut, grep
回到顶部
提取命令就是将一段数据经过分析后,取出我们想要的数据信息。大部分提取命令都是以行为单位进程信息提取。
cut就是切的意思,cut命令以行为单位将一行信息中的某一段切取出来。
cut常用命令格式如下所示:
[peter@study ~]$ cut -d'分隔字符' -f fields #用于有特定分隔字符 [peter@study ~]$ cut -c 字符区间 #用于排列整齐的信息选项与参数:
-d :后面接分隔字符。与-f一起使用;找出PATH环境变量中的第五个路径:
-f :依据-d的分隔字符将一段信息分区成为数段,用-f取出第几段的意思;
-c :以字符(characters)的单位取出固定字符区间;
[peter@study ~]$ echo ${PATH} /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games [peter@study ~]$ echo ${PATH} | cut -d ':' -f 5 /sbin上面就是将echo ${PATH}输出内容以:号分割,取出第五段内容。 如果想要列出第3与第5呢:
[peter@study ~]$ echo ${PATH} | cut -d ':' -f 3,5 /usr/sbin:/sbin将export输出的信息,取得第12字符以后的所有字符串:
[peter@study ~]$ export declare -x CINNAMON_SLOWDOWN_FACTOR="0.0001" declare -x CINNAMON_SOFTWARE_RENDERING="1" declare -x CINNAMON_VERSION="4.0.10" declare -x COLORTERM="truecolor" declare -x DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/1000/bus" declare -x DEFAULTS_PATH="/usr/share/gconf/cinnamon.default.path" declare -x DESKTOP_SESSION="cinnamon" ...省略...可以看到上面的的每一行最前面都是declare -x,可以不需要declare -x:
[peter@study ~]$ export | cut -c 12- CINNAMON_SLOWDOWN_FACTOR="0.0001" CINNAMON_SOFTWARE_RENDERING="1" CINNAMON_VERSION="4.0.10" COLORTERM="truecolor" DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/1000/bus" DEFAULTS_PATH="/usr/share/gconf/cinnamon.default.path" DESKTOP_SESSION="cinnamon" ...省略...用 -c 可以处理比较具有格式的输出数据!
可以指定某个范围的值,例如第 12-20 的字符,就是 cut -c 12-20 等等!
用last命令列出登录用户信息,仅查看用户名:
[peter@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命令输出账号/终端机/来源/日期时间的登录数据。
[peter@study ~]$ last | cut -d ' ' -f 1由输出的结果我们可以发现第一个空白分隔的字段代表账号,所以使用如上命令。 但是因为root pts/1之间有好几个空格,所以,如果要找出pts/1其实不能以 cut -d ' ' -f 1,2。
cut主要的用途在于将同一行里面的数据,以某些字符作为分隔符进行分解切割,以取得我们所需要的数 据。最常使用在分析一些数据或文字数据的时候!尤其是在分析log文件的时候! 不过,cut在处理多空格相连的数据时,可能会比较吃力一点,所以某些时刻可能会使用awk来取代!
提取命令: grep
回到顶部
cut命令是提取一行中的某一段内容,而grep则是提取符合条件的一整行信息。
grep会分析一行信息, 如果该行有我们所需要的信息,就将整行信息提取出来:
[peter@study ~]$ grep [-acinv] [--color=auto] '搜寻字符串' filename选项与参数:
-a :将binary文件以text文件的方式搜寻数据;将last命令的输出中,输出带有root的行:
-c :计算找到'搜寻字符串'的次数;
-i :忽略大小写的不同,大小写视为相同;
-n :顺便输出行号;
-v :反向选择,亦即显示出没有'搜寻字符串'内容的那一行;
--color=auto :可以将找到的关键词部分加上颜色显示!
[peter@study ~]$ last | grep 'root'与上例相反,取出没有root的行:
[peter@study ~]$ last | grep -v 'root'在last的输出信息中,取出含有root的行,并且每行只取第一栏:
[peter@study ~]$ last | grep 'root' | cut -d ' ' -f 1# 在取出 root 之后,利用上个命令 cut 的处理,就能够仅取得第一栏啰!
取出/etc/manpath.conf文件中含有MANPATH的行:
[peter@study ~]$ grep --color=auto 'MANPATH' /etc/manpath.config ...省略... MANPATH_MAP /bin /usr/share/man MANPATH_MAP /usr/bin /usr/share/man MANPATH_MAP /sbin /usr/share/man ...省略...加上--color=auto选项,grep会将找到的关键词用特殊颜色显示! CentOS 7当中,alias grep='grep --color=auto',grep其实是grep --color=auto的命令别名。 默认就已经加上--color=auto了! grep可以解析一行文字,取得关键词,若该行有存在关键词,就会整行列出来! grep是个非常实用的命令!结合正则表达式,可以提取复杂的数据。关于正则表达式,我们稍后介绍。
双向重定向: tee
回到顶部
双向重定向: tee
输出重定向>或>>是将命令的标准(错误)输出重新定向到文件或者设备,输出重定向后,数据不会显示在屏幕上。
但是有时候,我们即想让数据输出到指定的文件或者设备,同时也希望数据还可以输出到屏幕。
tee可以同时将数据流输出到文件和标准输出,tee数据流示意图如下所示:
图 tee数据流示意图
[peter@study ~]$ tee [-a] file-a选项以累加(append)的方式,将数据写入file文件中!
tee可以让standard output转存一份到文件内并将同样的数据继续送到屏幕去处理! 这样除了可以让我们同时分析一份数据并记录下来之外,还可以作为处理一份数据的中间暂存盘记录之用!
将last的输出存一份到last.list 文件中;
[peter@study ~]$ last | tee last.list | cut -d " " -f1将ls的数据存一份到~/homefile,同时屏幕也有输出信息:
[peter@study ~]$ ls -l /home | tee ~/homefile | moretee后接的文件会被覆盖,加上-a选项则能将信息累加:
[peter@study ~]$ ls -l / | tee -a ~/homefile | more
linux wc命令
回到顶部wc命令用于统计输入的字数、行数和字符数。
[peter@study ~]$ wc [-lwm]选项与参数:
-l :仅列出行;统计/etc/manpath.config文件的行数、字数和字符数:
-w :仅列出多少字(英文单字);
-m :多少字符;
[peter@study ~]$ cat /etc/manpath.config | wc 131 715 5174输出的三个数字分别代表行数、字数和字符数
使用 last 可以输出登入者,但是 last 最后两行并非账号内容,该如何以一行命令串取得登入系统的总人次?
[peter@study ~]$ last | grep [a-zA-Z] | grep -v 'wtmp' | grep -v 'reboot' | \ > grep -v 'unknown' |wc -l由于 last 会输出空白行, wtmp, unknown, reboot 等无关账号登入的信息, 因此利用grep取出非空白行,以及去除上述关键词那几行,再计算行数,就可以了!
打印出账号文件中有多少个账号:
[peter@study ~]$ cat /etc/passwd | wc -l因为/etc/passwd文件中每一行代表一个用户! 所以只需要统计行数就可以知道有多少的账号了! 而如果要计算一个文件里头有多少个字符时,就使用 wc -m 这个选项吧!
join
回到顶部
join处理两个文件之间的数据,主要是在处理两个文件当中,有相同数据的那一行,才将他加join在一起
[peter@study ~]$ join [-ti12] file1 file2选项与参数:
-t :join 默认以空格符分隔数据,并且比对『第一个字段』的数据,如果两个文件相同,则将两笔数据联成一行,且第一个字段放在第一个!用 root 的身份,将 /etc/passwd 与 /etc/shadow 相关数据整合成一栏
-i :忽略大小写的差异;
-1 :这个是数字的1 ,代表第一个文件要用那个字段来分析的意思;
-2 :代表第二个文件要用那个字段来分析的意思。
[root@initroot ~]# sudo head -n 3 /etc/passwd /etc/shadow ==> /etc/passwd <== root:x:0:0:root:/root:/bin/bash daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin bin:x:2:2:bin:/bin:/usr/sbin/nologin ==> /etc/shadow <== root:$6$iWZdx1dL$UmMmRTYcPPYmIOLphHouLkfqbsy2k4uyLnekclB4LnBP9ksLDGCqZ5kTS/uxsl7D4umb1/.RrEJF/Xw0lDlDu/:18268:0:99999:7::: daemon:*:17882:0:99999:7::: bin:*:17882:0:99999:7:::从上面的输出可以看出这两个文件的最左边字段都是相同账号!且以 : 分隔
[root@initroot ~]# join -t ':' /etc/passwd /etc/shadow | head -n 3 root:x:0:0:root:/root:/bin/bash:$6$iWZdx1dL$UmMmRTYcPPYmIOLphHouLkfqbsy2k4uyLnekclB4LnBP9ksLDGCqZ5kTS/uxsl7D4umb1/.RrEJF/Xw0lDlDu/:18268:0:99999:7::: daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin:*:17882:0:99999:7::: bin:x:2:2:bin:/bin:/usr/sbin/nologin:*:17882:0:99999:7:::这样我们就可以将两个文件第一字段相同者整合成一行!第二个文件的相同字段并不会显示(因为已经在最左边的字段出现了啊!)
我们知道/etc/passwd第四个字段是GID ,那个GID记录在/etc/group文件中的第三个字段,请问如何将两个文件整合?
[root@initroot ~]# head -n 3 /etc/passwd /etc/group ==> /etc/passwd <== root:x:0:0:root:/root:/bin/bash daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin bin:x:2:2:bin:/bin:/usr/sbin/nologin ==> /etc/group <== root:x:0:peter daemon:x:1: bin:x:2:从上面可以看到,确实有相同的部分喔!赶紧来整合一下!
[root@initroot ~]# join -t ':' -1 4 /etc/passwd -2 3 /etc/group | head -n 3 join: /etc/passwd:6: is not sorted: games:x:5:60:games:/usr/games:/usr/sbin/nologin join: /etc/group:11: is not sorted: uucp:x:10: 0:root:x:0:root:/root:/bin/bash:root:x:peter 1:daemon:x:1:daemon:/usr/sbin:/usr/sbin/nologin:daemon:x: 2:bin:x:2:bin:/bin:/usr/sbin/nologin:bin:x:# 同样的,相同的字段部分被移动到最前面了!所以第二个文件的内容就没再显示。
# 请读者们配合上述显示两个文件的实际内容来比对!
这个 join 在处理两个相关的数据文件时,就真的是很有帮助的啦! 例如上面的案例当中, 我的/etc/passwd, /etc/shadow, /etc/group 都是有相关性的, 其中 /etc/passwd, /etc/shadow 以账号为相关性,
至于/etc/passwd, /etc/group则以所谓的GID(账号的数字定义) 来作为他的相关性。 根据这个相关性,我们可以将有关系的资料放置在一起!这在处理数据可是相当有帮助的! 但是上面的例子有点难,希望您可以静下心好好的看一看原因喔!此外,需要特别注意的是,在使用 join 之前,你所需要处理的文件应该要事先经过排序 (sort) 处理!
否则有些比对的项目会被略过呢!特别注意了!
col
回到顶部
[peter@study ~]$ col [-xb]选项与参数:
-x:将tab键转换成对等的空格键
利用 cat -A 显示出所有特殊按键,最后以col将[tab]转成空白:
[peter@study ~]$ cat -A /etc/man_db.conf #此时会看到很多 ^I 的符号,那就是 tab [peter@study ~]$ cat /etc/man_db.conf | col -x | cat -A | more这样tab键会被取代成为空格键,输出就美观多了!
虽然 col 有他特殊的用途,不过,很多时候,他可以用来简单的处理将tab按键取代成为空格键!
例如上面的例子当中,如果使用 cat -A 则 [tab] 会以 ^I 来表示。 但经过 col -x 的处理,则会将 [tab]取代成为对等的空格键!
expand
回到顶部
expand将tab键转成空格键:
[peter@study ~]$ expand [-t] file选项与参数: -t:后面可以接数字。一般来说,一个 tab 按键可以用 8 个空格键取代。 我们也可以自行定义一个 [tab] 按键代表多少个字符呢!
将 /etc/man_db.conf 内行首为 MANPATH 的字样就取出;仅取前三行;
[peter@study ~]$ grep '^MANPATH' /etc/manpath.config | head -n 3 MANPATH_MAP /bin /usr/share/man MANPATH_MAP /usr/bin /usr/share/man MANPATH_MAP /sbin /usr/share/man行首的代表标志为^,这个我们留待下节介绍!先有概念即可!
用cat将所有的符号都列出来:
[peter@study ~]$ grep '^MANPATH' /etc/manpath.config | 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个字符:
[peter@study ~]$ grep '^MANPATH' /etc/manpath.config | 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$上面是以6个字符来代表一个tab的长度,所以MAN...到/usr之间会隔12(两个tab)个字符!如果tab改成9,情况就又不同了!
expand自动将tab转成空格键,所以,以上面的例子来说, 使用 cat -A 就会查不到 ^I 的字符。 此外,因为tab最大的功能就是格式排列整齐! 我们转成空格键后,这个空格键也会依据我们自己的定义来增加大小~ 所以,并不是一个^I就会换成8个空白喔! 这个地方要特别注意的哩! 此外,您也可以参考一下unexpand这个将空白转成tab的命令功能!
paste
回到顶部
paste就要比join 简单多了!相对于join 必须要比对两个文件的数据相关性,
paste直接将两行贴在一起,且中间以tab键隔开!简单的使用方法:
[peter@study ~]$ paste [-d] file1 file2选项与参数:
-d :后面可以接分隔字符。预设是以 [tab] 来分隔的!用 root 身份,将 /etc/passwd 与 /etc/shadow 同一行贴在一起:
- :如果 file 部分写成 - ,表示来自 standard input 的资料的意思。
[root@initroot ~]# paste /etc/passwd /etc/shadow root:x:0:0:root:/root:/bin/bash root:$6$iWZdx1dL$UmMmRTYcPPYmIOLphHouLkfqbsy2k4uyLnekclB4LnBP9ksLDGCqZ5kTS/uxsl7D4umb1/.RrEJF/Xw0lDlDu/:18268:0:99999:7::: daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin daemon:*:17882:0:99999:7::: bin:x:2:2:bin:/bin:/usr/sbin/nologin bin:*:17882:0:99999:7::: sys:x:3:3:sys:/dev:/usr/sbin/nologin sys:*:17882:0:99999:7::: sync:x:4:65534:sync:/bin:/bin/sync sync:*:17882:0:99999:7::: ...省略...注意同一行中间以tab键隔开!
先将 /etc/group 读出(用 cat),然后与范例一贴上一起!且仅取出前三行
[root@initroot ~]# cat /etc/group | paste /etc/passwd /etc/shadow - | head -n 3 root:x:0:0:root:/root:/bin/bash root:$6$iWZdx1dL$UmMmRTYcPPYmIOLphHouLkfqbsy2k4uyLnekclB4LnBP9ksLDGCqZ5kTS/uxsl7D4umb1/.RrEJF/Xw0lDlDu/:18268:0:99999:7::: root:x:0:peter daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin daemon:*:17882:0:99999:7::: daemon:x:1: bin:x:2:2:bin:/bin:/usr/sbin/nologin bin:*:17882:0:99999:7::: bin:x:2:重点在那个 - 的使用!那玩意儿常常代表 stdin 喔!
排序命令: sort, wc, uniq
回到顶部
很多时候,我们都会去计算一次数据里头的相同型态的数据总数,举例来说, 使用 last 可以查得系
统上面有登入主机者的身份。那么我可以针对每个使用者查出他们的总登入次数吗? 此时就得要排
序与计算之类的命令来辅助了!底下我们介绍几个好用的排序与统计命令喔!
sort
回到顶部
sort可以依据不同的数据型态对行进行排序! 例如数字与文字的排序就不一样。
此外,排序的字符与语系编码有关,排序前,建议使用LANG=C让语系统一,数据排序比较好一些。
[peter@study ~]$ sort [-fbMnrtuk] [file or stdin]选项与参数:
-f :忽略大小写的差异,例如 A 与 a 视为编码相同;对/etc/passwd文件中的用户账号进行排序:
-b :忽略最前面的空格符部分;
-M :以月份的名字来排序,例如 JAN, DEC 等等的排序方法;
-n :使用数值型进行排序(默认是以字符型态来排序的);
-r :反向排序;
-u :就是 uniq ,相同的数据中,仅出现一行代表;
-t :分隔符,预设是用 [tab] 键来分隔;
-k :以那个区间 (field) 来进行排序的意思
[peter@study ~]$ cat /etc/passwd | sort _apt:x:104:65534::/nonexistent:/usr/sbin/nologin avahi-autoipd:x:109:114:Avahi autoip daemon,,,:/var/lib/avahi-autoipd:/usr/sbin/nologin avahi:x:115:122:Avahi mDNS daemon,,,:/var/run/avahi-daemon:/usr/sbin/nologin backup:x:34:34:backup:/var/backups:/usr/sbin/nologin bin:x:2:2:bin:/bin:/usr/sbin/nologin colord:x:116:123:colord colour management daemon,,,:/var/lib/colord:/usr/sbin/nologin cups-pk-helper:x:106:112:user for cups-pk-helper service,,,:/home/cups-pk-helper:/usr/sbin/nologin daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin ...省略...由上面的数据可以看出, sort默认以第一个字段数据来排序,并且默认是以字符型来排序!
将/etc/passwd文件中的内容以第三个字段排序:
[peter@study ~]$ cat /etc/passwd | sort -t ':' -k 3 root:x:0:0:root:/root:/bin/bash peter:x:1000:1000:peter,,,:/home/peter:/bin/bash systemd-network:x:100:102:systemd Network Management,,,:/run/systemd/netif:/usr/sbin/nologin mysql:x:1001:1001::/home/mysql:/sbin/nologin www:x:1002:1002::/home/www:/sbin/nologin uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin systemd-resolve:x:101:103:systemd Resolver,,,:/run/systemd/resolve:/usr/sbin/nologin ...省略.../etc/passwd文件中的字段是以:作为分隔符,所以需要用-t指定分隔符。由于sort默认是以字符型排序,上面我们可以看到100在1000的后面。 需要使用-n选项,这样sort就会把第三个字段作为数值进行排序:
[peter@study ~]$ cat /etc/passwd | sort -t ':' -k 3 -n root:x:0:0:root:/root:/bin/bash daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin bin:x:2:2:bin:/bin:/usr/sbin/nologin sys:x:3:3:sys:/dev:/usr/sbin/nologin sync:x:4:65534:sync:/bin:/bin/sync games:x:5:60:games:/usr/games:/usr/sbin/nologin man:x:6:12:man:/var/cache/man:/usr/sbin/nologin lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin ...省略...sort是很常用的命令。假设有很多的账号,想要知道最大的用户ID目前到哪一号了!使用sort就可以很容易知道答案了!
取last输出中的账号信息并加以排序:
[peter@study ~]$ last | cut -d ' ' -f1 | sort
分区命令: split
回到顶部
split可以将一个大文件,依据文件大小或行数来分区,就可以将大文件分区成为小文件了!
如果你有文件太大,导致一些携带式装置无法复制的问题,就可以先用split将大文件分割成多个小文件。
[peter@study ~]$ split [-bl] file PREFIX选项与参数:
-b :后面可接欲分区成的文件大小,可加单位,例如 b, k, m 等;/etc/services文件有六百多K,若想要分成300K一个文件时:
-l :以行数来进行分区。
PREFIX :代表前导符的意思,可作为分区文件的前导文字。
[peter@study ~]$ cd /tmp; split -b 300k /etc/services services [peter@study tmp]$ ll -k services* -rw-rw-r--. 1 peter peter 307200 Jul 9 22:52 servicesaa -rw-rw-r--. 1 peter peter 307200 Jul 9 22:52 servicesab -rw-rw-r--. 1 peter peter 9 22:52 servicesac 55893 Jul文件名可以随意指定!只要写上前导文字,小文件就会以xxxaa, xxxab, xxxac等方式来建立小文件的!
将上面的三个小文件合成一个文件,文件名为 servicesback:
[peter@study tmp]$ cat services* >> servicesback就用数据流重导向就好啦!简单!
使用ls -al /输出的信息中,每十行记录成一个文件
[peter@study tmp]$ ls -al / | split -l 10 - lsroot [peter@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!
字符转换命令: tr, col, join, paste, expand
回到顶部
我们在 vim 程序编辑器当中,提到过 DOS 断行字符与 Unix 断行字符的不同,并且可以使用
dos2unix 与 unix2dos 来完成转换。好了,那么思考一下,是否还有其他常用的字符替代? 举例来
说,要将大写改成小写,或者是将数据中的 [tab] 按键转成空格键?还有,如何将两篇信息整合成一
篇? 底下我们就来介绍一下这些字符转换命令在管道当中的使用方法:
tr
回到顶部
tr可以用来删除一段信息当中的文字,或者是进行文字信息的替换!
[peter@study ~]$ tr [-ds] SET1 ...选项与参数:
-d :删除信息当中的 SET1 这个字符串;将 last 输出的信息中,所有的小写变成大写字符:
-s :取代掉重复的字符!
[peter@study ~]$ last | tr '[a-z]' '[A-Z]'没有加上单引号也是可以执行的,如:last | tr [a-z] [A-Z]
将/etc/passwd输出的信息中,将冒号(:)删除:
[peter@study ~]$ cat /etc/passwd | tr -d ':'将/etc/passwd转存成dos断行到/root/passwd中,再将^M符号删除:
[peter@study ~]$ cp /etc/passwd ~/passwd && unix2dos ~/passwd [peter@study ~]$ file /etc/passwd ~/passwd /etc/passwd: ASCII text /home/peter/passwd: ASCII text, with CRLF line terminators #就是 DOS 断行 [peter@study ~]$ cat ~/passwd | tr -d '\r' > ~/passwd.linux # 那个 \r 指的是 DOS 的断行字符,关于更多的字符,请参考 man tr [peter@study ~]$ ll /etc/passwd ~/passwd* -rw-r--r--. 1 root root 2092 Jun 17 00:20 /etc/passwd -rw-r--r--. 1 peter peter 2133 Jul 9 22:13 /home/peter/passwd -rw-rw-r--. 1 peter peter 2092 Jul 9 22:13 /home/peter/passwd.linux# 处理过后,发现文件大小与原本的 /etc/passwd 就一致了!
其实这个命令也可以写在『正规表示法』里头!因为他也是由正规表示法的方式来取代数据的! 以 上面的例子来说,使用 [] 可以设定一串字呢!也常常用来取代文件中的怪异符号! 例如上面第三 个例子当中,可以去除 DOS 文件留下来的 ^M 这个断行的符号!这东西相当的有用!相信处理Linux & Windows 系统中的人们最麻烦的一件事就是这个事情啦! 亦即是 DOS 底下会自动的在每行行尾加入 ^M 这个断行符号!这个时候除了以前讲过的 dos2unix 之外,我们也可以使用这个 tr 来 将 ^M 去除! ^M 可以使用 \r 来代替之!
uniq将输入中重复的行去掉。如果排序完成了,想要将重复的资料仅列出一个显示,就可以用uniq命令
[peter@study ~]$ uniq [-ic]选项与参数:
-i :忽略大小写字符的不同;uniq命令用来将重复的行删除掉只显示一个 要知道这个月份登入你主机的用户有谁,而不在乎他的登入次数, 那么就可以取出last输出的账号字段,排序后,去掉重复的行:
-c :进行计数
[peter@study ~]$ last | cut -d ' ' -f1 | sort | uniq上面的步骤为:
(1)先将所有的数据列出;
(2)再将人名独立出来;
(3)经过排序;
(4)只显示一个! 由于这个命令是在将重复的东西减少,所以当然需要配合排序过的文件』来处理!
上面去掉重复的行后,大部分情况需要统计出现的次数,也就是说,
[peter@study ~]$ last | cut -d ' ' -f1 | sort | uniq -c 1 42 peter 36 reboot 7 root 1 wtmp从上面的结果可以发现reboot有36次登录, root登入则有7次!而peter则登录了42次 !
wtmp 与第一行的空白都是 last 的默认字符,那两个可以忽略的!
参数代换: xargs
回到顶部
xargs 是在做什么的呢?就以字面上的意义来看, x 是加减乘除的乘号,args 则是 arguments (参数)
的意思,所以说,这个玩意儿就是在产生某个命令的参数的意思! xargs 可以读入 stdin 的数据,并
且以空格符或断行字符作为分辨,将 stdin 的资料分隔成为 arguments 。 因为是以空格符作为分隔,
所以,如果有一些文件名或者是其他意义的名词内含有空格符的时候, xargs 可能就会误判了~他的
用法其实也还满简单的!就来看一看先!
[peter@study ~]$ xargs [-0epn] command选项与参数:
-0 :如果输入的 stdin 含有特殊字符,例如 `, \, 空格键等等字符时,这个 -0 参数 可以将他还原成一般字符。这个参数可以用于特殊状态喔!当 xargs 后面没有接任何的命令时,默认是以 echo 来进行输出喔!
-e :这个是 EOF (end of file) 的意思。后面可以接一个字符串,当 xargs 分析到这个字符串时, 就会停止继续工作!
-p :在执行每个命令的 argument 时,都会询问使用者的意思;
-n :后面接次数,每次 command 命令执行时,要使用几个参数的意思。
范例一:将 /etc/passwd 内的第一栏取出,仅取三行,使用 id 这个命令将每个账号内容秀出来
[peter@study ~]$ id root uid=0(root) gid=0(root) groups=0(root)# 这个 id 命令可以查询用户的 UID/GID 等信息
[peter@study ~]$ id $(cut -d ':' -f 1 /etc/passwd | head -n 3)# 虽然使用 $(cmd) 可以预先取得参数,但可惜的是, id 这个命令『仅』能接受一个参数而已!
# 所以上述的这个命令执行会出现错误!根本不会显示用户的 ID 啊!
[peter@study ~]$ cut -d ':' -f 1 /etc/passwd | head -n 3 | iduid=1000(peter) gid=1000(peter) groups=1000(peter),10(wheel)# 我不是要查自己啊!
# 因为 id 并不是管道命令,因此在上面这个命令执行后,前面的东西通通不见!只会执行 id!
[peter@study ~]$ cut -d ':' -f 1 /etc/passwd | head -n 3 | xargs id# 依旧会出现错误!这是因为 xargs 一口气将全部的数据通通丢给 id 处理~但 id 就接受 1 个啊最多!
[peter@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 时,都要询问使用者是否动作?
[peter@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 就结束命令串
[peter@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 列出详细属性
[peter@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@initroot ~]# mkdir /tmp/homeback [root@initroot ~]# tar -cvf - /home | tar -xvf - -C /tmp/homeback上面这个例子是说:『我将 /home 里面的文件给他打包,但打包的数据不是纪录到文件,而是传送 到 stdout; 经过管道后,将 tar -cvf - /home 传送给后面的 tar -xvf - 』。后面的这个 - 则是取用前 一个命令的 stdout, 因此,我们就不需要使用 filename 了!这是很常见的例子喔!注意注意!
本文由initroot编辑整理,转载请注明www.initroot.com