您的位置:首页 > 运维架构 > Shell

shell字符截取与字符处理命令

2017-04-19 00:00 357 查看

1.使用cut命令截取列

grep适用于截取行的,cut是用于截取列的

1.1 用-f选项指定提取的列

###创建score.txt文件用于测试(注意列之间并不是空格,而是制表符,及Tab键)
[root@wenhaijin ~]# vim score.txt
ID      NAME    SEX     SCORE
1       ZHANGSAN        F       90
2       LISI    M       85
3       WANGWU  M       75

###截取第二列和第四列
[root@wenhaijin ~]# cut -f 2,4 score.txt
NAME    SCORE
ZHANGSAN        90
LISI    85
WANGWU  75


1.2 cut使用-d指定列的分隔符(默认的分隔符就是制表符)

有些文件并不是以制表符进行分割的,比如/etc/passwd文件使用":"来 分割列的,

这样我们就可以用cut -d ":"来进行提取

###截取用户列表(第一列)和用户id(第三列)
[root@wenhaijin ~]# cut -d ":" -f 1,3 /etc/passwd
root:0
bin:1
daemon:2
adm:3
lp:4
sync:5
shutdown:6
halt:7
mail:8
uucp:10
operator:11
games:12
gopher:13
ftp:14
user1:503
user2:504
user3:505


1.3 在实际应用中,cut经常是配合grep进行使用

###找出普通用户(命令保存在/bin/bash下)
[root@wenhaijin ~]# cat /etc/passwd | grep /bin/bash
root:x:0:0:root:/root:/bin/bash
mysql:x:498:500::/home/mysql:/bin/bash
wenhaijin:x:500:501::/home/wenhaijin:/bin/bash
whj:x:501:502::/home/whj:/bin/bash
fuzhoudaxue:x:502:503::/home/fuzhoudaxue:/bin/bash
user1:x:503:506::/home/user1:/bin/bash
user2:x:504:507::/home/user2:/bin/bash
user3:x:505:509::/home/user3:/bin/bash
[root@wenhaijin ~]#

###过滤掉超级用户(使用grep -v取反)
[root@wenhaijin ~]# cat /etc/passwd | grep /bin/bash | grep -v root
mysql:x:498:500::/home/mysql:/bin/bash
wenhaijin:x:500:501::/home/wenhaijin:/bin/bash
whj:x:501:502::/home/whj:/bin/bash
fuzhoudaxue:x:502:503::/home/fuzhoudaxue:/bin/bash
user1:x:503:506::/home/user1:/bin/bash
user2:x:504:507::/home/user2:/bin/bash
user3:x:505:509::/home/user3:/bin/bash
[root@wenhaijin ~]#

###只显示用户名
[root@wenhaijin ~]# cat /etc/passwd | grep /bin/bash | grep -v root | cut -d ":" -f 1
mysql
wenhaijin
whj
fuzhoudaxue
user1
user2
user3
[root@wenhaijin ~]#

###后续如果需要对除root用户外的所有普通用户进行相关处理(比如删除),就可以使用该命令,
将该命令的执行结果当做参数传递给shell脚本就行相关逻辑操作

cut命令比较简单,它的缺点是不能很好地使用cut -d " "来进行截取,因为有些列之间可能不止一个空格,cut会将第一个空格当做分隔符,第二个空格当做列,第三个空格又当做分隔符……

###以下是想得到根分区所在磁盘的使用百分比
###先查看系统所有分区
[root@wenhaijin ~]# df -h
Filesystem      Size  Used Avail Use% Mounted on
/dev/vda1        40G  7.3G   30G  20% /
tmpfs           939M  4.0K  939M   1% /dev/shm

###使用根分区的特性进行过滤
[root@wenhaijin ~]# df -h | grep "vda1"
/dev/vda1        40G  7.3G   30G  20% /

###使用cut -f 提取第五列(提取失败,说明并不是以制表符进行分割的)
[root@wenhaijin ~]# df -h | grep "vda1" | cut -f 5
/dev/vda1        40G  7.3G   30G  20% /

###使用空格来分割列,(答应出的是空格,因为第一列和第二列中有多个空格)
[root@wenhaijin ~]# df -h | grep "vda1" | cut -d " " -f 5

[root@wenhaijin ~]#


2.格式化输出命令printf

严格意义上说,printf并不是文件提取命令,也没有cat和echo使用起来方便。但是在awk中,不能直接调用cat和echo,而是需要通过调用printf来打印一些信息

2.1 printf

###使用printf打印上面的分数表内容score.txt
[root@wenhaijin ~]# printf '%s\t %s\t %s\t %s\n' $(cat score.txt)
ID       NAME    SEX     SCORE
1        ZHANGSAN        F       90
2        LISI    M       85
3        WANGWU  M       75
[root@wenhaijin ~]#


2.2 awk中print与printf的区别

print会在输出后自动加入换行符,但print并不是linx系统命令,所以不能在系统中直接调用

3 awk命令

3.1 awk命令的用法

###使用awk命令输出score.txt的姓名(第二列)和成绩(第四列)
[root@wenhaijin ~]# awk '{printf $2 $4}' score.txt
NAMESCOREZHANGSAN90LISI85WANGWU75[root@wenhaijin ~]#

###配合制表符和换行符进行格式化
[root@wenhaijin ~]# awk '{printf $2 "\t" $4"\n"}' score.txt
NAME    SCORE
ZHANGSAN        90
LISI    85
WANGWU  75
[root@wenhaijin ~]#

###查看磁盘使用情况
[root@wenhaijin ~]# df -h
Filesystem      Size  Used Avail Use% Mounted on
/dev/vda1        40G  7.3G   30G  20% /
tmpfs           939M  4.0K  939M   1% /dev/shm

###查看第一列,第五列,第六列(未进行格式化)
[root@wenhaijin ~]# df -h | awk '{printf $1 "\t" $5 "\t" $6}'
Filesystem      Use%    Mounted/dev/vda1        20%     /tmpfs  1%      /dev/shm

###print自带换行功能
[root@wenhaijin ~]# df -h | awk '{print $1 "\t" $5 "\t" $6}'
Filesystem      Use%    Mounted
/dev/vda1       20%     /
tmpfs   1%      /dev/shm
[root@wenhaijin ~]#

###查看根分区使用情况(第五列)
[root@wenhaijin ~]# df -h | grep vda1 | awk '{print $5}'
20%

###只提取根分区数字,不显示百分比
[root@wenhaijin ~]# df -h | grep vda1 | awk '{print $5}' | cut -d "%" -f 1
20


3.2 BEGIN用法

BEGIN在所有的awk条件执行之前执行,且只执行一次

###在打印学生成绩之前打印一句话
[root@wenhaijin ~]# awk 'BEGIN{print "The of all students is bellow:"} {printf $2 "\t" $4"\n"}' score.txt
The of all students is bellow:
NAME    SCORE
ZHANGSAN        90
LISI    85
WANGWU  75
[root@wenhaijin ~]#


3.3 用FS内置变量用来指定分隔符

/etc/passwd是用":"分割的,用FS指定分隔符

###打印出密码文件中的用户名和用户ID
[root@wenhaijin ~]# awk '{FS=":"} {print $1 "\t" $3}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin     1
daemon  2
adm     3
lp      4
sync    5
shutdown        6
halt    7
mail    8
uucp    10
operator        11
games   12
gopher  13
ftp     14
nobody  99
dbus    81
vcsa    69
abrt    173
haldaemon       68
ntp     38
saslauth        499
postfix 89
sshd    74
tcpdump 72
nscd    28
mysql   498
wenhaijin       500
whj     501
fuzhoudaxue     502
user1   503
user2   504
user3   505
[root@wenhaijin ~]#

从上面的输出结果可以看出,awk命令并没有对第一行进行处理,原因是awk在处理的时候是先读取第一行数据,然后再执行后面的操作,也就是说在上面的awk命令中,通过FS指定分隔符之前,第一行数据已经被读入,后面的按列输出处理就来不及了。对于第一行,awk其实是采用默认的空格来进行分割

解决方法就是通过3.2中的BEGIN命令来处理

###使用BEGIN命令,表示在读取第一行数据前就先指定分隔符
[root@wenhaijin ~]# awk 'BEGIN{FS=":"} {print $1 "\t" $3}' /etc/passwd
root    0
bin     1
daemon  2
adm     3
lp      4
sync    5
shutdown        6
halt    7
mail    8
uucp    10
operator        11
games   12
gopher  13
ftp     14
nobody  99
dbus    81
vcsa    69
abrt    173
haldaemon       68
ntp     38
saslauth        499
postfix 89
sshd    74
tcpdump 72
nscd    28
mysql   498
wenhaijin       500
whj     501
fuzhoudaxue     502
user1   503
user2   504
user3   505
[root@wenhaijin ~]#


3.4 END的用法

在awk命令中,END所指定的操作会在所有操作执行完成之后再执行,END条件操作不一定要写在最后,跟书写顺序无关

[root@wenhaijin ~]# awk 'BEGIN{print "The of all students is bellow:"} END{print "This is the endding!"} {printf $2 "\t" $4"\n"}' score.txt
The of all students is bellow:
NAME    SCORE
ZHANGSAN        90
LISI    85
WANGWU  75
This is the endding!
[root@wenhaijin ~]#


3.5 awk条件运算符的使用

[root@wenhaijin ~]# cat score.txt
ID      NAME    SEX     SCORE
1       ZHANGSAN        F       90
2       LISI    M       85
3       WANGWU  M       75
[root@wenhaijin ~]#

###打印出成绩大于或等于80分的学生姓名
[root@wenhaijin ~]# cat score.txt | grep -v name | awk '$4 >= 80 {print $2}'
NAME
ZHANGSAN
LISI
[root@wenhaijin ~]#


4 sed命令

sed的选项一定要用单引号括起来,sed对应的当做有下面几种:

4.1 sed命令可以处理文件

###输出score.txt的第二行信息,结果是所有信息都输出,第二行输出了两遍
[root@wenhaijin ~]# sed "2p" score.txt
ID      NAME    SEX     SCORE
1       ZHANGSAN        F       90
1       ZHANGSAN        F       90
2       LISI    M       85
3       WANGWU  M       75
[root@wenhaijin ~]#

###采用-n选项只输出sed过滤的行
[root@wenhaijin ~]# sed -n "2p" score.txt
1       ZHANGSAN        F       90
[root@wenhaijin ~]#


4.2 sed命令是流编辑器,他也能放在管道符之后处理前面输出的内容

###打印df -h 中的第二行数据
[root@wenhaijin ~]# df -h | sed -n "2p"
/dev/vda1        40G  5.9G   32G  16% /
[root@wenhaijin ~]#


4.3 sed删除行

###sed删除文件的第二行到第四行
[root@wenhaijin ~]# sed "2,4d" score.txt
ID      NAME    SEX     SCORE

###sed删除文件的第三行
[root@wenhaijin ~]# sed "3d" score.txt
ID      NAME    SEX     SCORE
1       ZHANGSAN        F       90
3       WANGWU  M       75

###查看文件发现 文件真正的内容并没有被删除
[root@wenhaijin ~]# cat score.txt
ID      NAME    SEX     SCORE
1       ZHANGSAN        F       90
2       LISI    M       85
3       WANGWU  M       75
[root@wenhaijin ~]#


4.4 追加与插入

###在第二行后追加一行:hello-world
[root@wenhaijin ~]# sed '2a hello-world' score.txt
ID      NAME    SEX     SCORE
1       ZHANGSAN        F       90
hello-world
2       LISI    M       85
3       WANGWU  M       75
[root@wenhaijin ~]#

###在第二行前插入:hello-kitty
[root@wenhaijin ~]# sed '2i hello-kitty' score.txt
ID      NAME    SEX     SCORE
hello-kitty
1       ZHANGSAN        F       90
2       LISI    M       85
3       WANGWU  M       75
[root@wenhaijin ~]#

###在第二行前面同时插入两行
[root@wenhaijin ~]# sed '2i hello-kitty1 \
> hello-kitty2' score.txt
ID      NAME    SEX     SCORE
hello-kitty1
hello-kitty2
1       ZHANGSAN        F       90
2       LISI    M       85
3       WANGWU  M       75
[root@wenhaijin ~]#


4.5 sed字符替换

行替换

[root@wenhaijin ~]# cat score.txt
ID      NAME    SEX     SCORE
1       ZHANGSAN        F       90
2       LISI    M       85
3       WANGWU  M       75

###将第四行替换成Only two person
[root@wenhaijin ~]# sed '4c Only two person' score.txt
ID      NAME    SEX     SCORE
1       ZHANGSAN        F       90
2       LISI    M       85
Only two person
[root@wenhaijin ~]#


###替换张三的成绩为60分
[root@wenhaijin ~]# sed '2s/90/60/g' score.txt
ID      NAME    SEX     SCORE
1       ZHANGSAN        F       60
2       LISI    M       85
3       WANGWU  M       75
[root@wenhaijin ~]#

###以上操作的只是输出内容,并没有真正改变文件
[root@wenhaijin ~]# cat score.txt
ID      NAME    SEX     SCORE
1       ZHANGSAN        F       90
2       LISI    M       85
3       WANGWU  M       75
[root@wenhaijin ~]#

###将张三的成绩改成80分并写入文件
[root@wenhaijin ~]# sed -i '2s/90/80/g' score.txt
[root@wenhaijin ~]# cat score.txt
ID      NAME    SEX     SCORE
1       ZHANGSAN        F       80
2       LISI    M       85
3       WANGWU  M       75
[root@wenhaijin ~]#

###多行替换,未指定行及替换整个文档,将张三改为赵六,李四改为空
[root@wenhaijin ~]# sed -e 's/ZHANGSAN/ZHAOLIU/g ; s/LISI//g' score.txt
ID      NAME    SEX     SCORE
1       ZHAOLIU F       80
2               M       85
3       WANGWU  M       75
[root@wenhaijin ~]#


5 字符处理命令

5.1 字符排序

###按字符顺序对/etc/passwd进行排序
[root@wenhaijin ~]# sort /etc/passwd
abrt:x:173:173::/etc/abrt:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
dbus:x:81:81:System message bus:/:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
tcpdump:x:72:72::/:/sbin/nologin
user1:x:503:506::/home/user1:/bin/bash
user2:x:504:507::/home/user2:/bin/bash
user3:x:505:509::/home/user3:/bin/bash
uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin
vcsa:x:69:69:virtual console memory owner:/dev:/sbin/nologin
wenhaijin:x:500:501::/home/wenhaijin:/bin/bash
whj:x:501:502::/home/whj:/bin/bash

###按字母顺序反向排序
[root@wenhaijin ~]# sort -r /etc/passwd
whj:x:501:502::/home/whj:/bin/bash
wenhaijin:x:500:501::/home/wenhaijin:/bin/bash
vcsa:x:69:69:virtual console memory owner:/dev:/sbin/nologin
uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin
user3:x:505:509::/home/user3:/bin/bash
user2:x:504:507::/home/user2:/bin/bash
user1:x:503:506::/home/user1:/bin/bash
tcpdump:x:72:72::/:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
dbus:x:81:81:System message bus:/:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
bin:x:1:1:bin:/bin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
abrt:x:173:173::/etc/abrt:/sbin/nologin
[root@wenhaijin ~]#

###按照第三列(用户ID)进行排序,用户ID虽然是数字类型,sort默认依然按字母来排
###指定分隔符是":",用第三个字段开头,第三个字段结尾(即只用第三个字段)排序
[root@wenhaijin ~]# sort -t ":" -k 3,3 /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
abrt:x:173:173::/etc/abrt:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
nscd:x:28:28:NSCD Daemon:/:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
wenhaijin:x:500:501::/home/wenhaijin:/bin/bash
whj:x:501:502::/home/whj:/bin/bash
user1:x:503:506::/home/user1:/bin/bash
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
postfix:x:89:89::/var/spool/postfix:/sbin/nologin
nobody:x:99:99:Nobody:/:/sbin/nologin
[root@wenhaijin ~]#

###通过-n选项指定以数字顺序排
[root@wenhaijin ~]# sort -n -t ":" -k 3,3 /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
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
gopher:x:13:30:gopher:/var/gopher:/sbin/nologin
ntp:x:38:38::/etc/ntp:/sbin/nologin
haldaemon:x:68:68:HAL daemon:/:/sbin/nologin
vcsa:x:69:69:virtual console memory owner:/dev:/sbin/nologin
tcpdump:x:72:72::/:/sbin/nologin
mysql:x:498:500::/home/mysql:/bin/bash
saslauth:x:499:76:"Saslauthd user":/var/empty/saslauth:/sbin/nologin
wenhaijin:x:500:501::/home/wenhaijin:/bin/bash
whj:x:501:502::/home/whj:/bin/bash
fuzhoudaxue:x:502:503::/home/fuzhoudaxue:/bin/bash
user1:x:503:506::/home/user1:/bin/bash
user3:x:505:509::/home/user3:/bin/bash
[root@wenhaijin ~]#


5.2 统计命令wc

统计/etc/passwd文件

###这个文件有32行,42个单词,1388个字符
[root@wenhaijin ~]# wc /etc/passwd
32   42 1388 /etc/passwd
[root@wenhaijin ~]#

###只统计行数
[root@wenhaijin ~]# wc -l /etc/passwd
32 /etc/passwd

###只统计单词
[root@wenhaijin ~]# df -h | wc -w
19

###只统计字符数
[root@wenhaijin ~]# df -h | wc -m
136
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息