现在的位置: 首页 > 综合 > 正文

shell实现文本处理详解

2019年04月19日 ⁄ 综合 ⁄ 共 4641字 ⁄ 字号 评论关闭

1. 排序文本

1.1. sort 命令

sort 命令可以帮助我们排序,而且可以根据不同的数据类型来排序。

1.1.1 语法与参数

语法

    sort[options]

]

用途

    将愉入行按照健值字段与数据类型选项以及 locale 排序。

主要选项

-b 忽略开头的空白。

-c 检查输入是否已正确地排序。如输入未经排序,但退出码 (exit code 为非零值 ) ,则不会有任何输出。

-d 字典顺序 : 仅文字数字与空白才有意义。

-g 一般数位 : 以浮点数字类型比较宇段。这个选项的运作有点类似一 n, 差别仅在于这个选项的数字可能有小数点及指数 ( 例 :s.oaz}+z3) 。

-i 将混用的字母都看作相同大小写,也就是以不管字母大小写的方式排序。

忽略无法打印的字符。

-k 定义排序健值字段。见下表 1 。

-m 将已排序的输入文件,合并为一个排序后的愉出数据流。

-n 以整数类型比较字段。

-o outfile

      将愉出写到指定的文件,而非标准输出。如果该文件为输入文件之一,则 sort 在进行排序与写到输出文件之前,会先将它复制到一个临时的文件。

-r 倒置排序的顺序为由大至小 (descending) ,而非默认的由小至 ([ascending] 。

-t char

       使用单个字符char 作为默认认的字段分隔字符,取代默认的空白字符。

-u 只有唯一的记录: 丢弃所有具相同健值的记录,只留其中的第一条。只有健值字段是重要的,也就是说:被丢弃的记录其他部分可能是不同值。

表1: 排序键值字段的类型

字母

说明

b

忽略开头的空白

d

字典顺序

f

不区分字母的大小写

g

以一般的符点数字进行比较,只适用于GNU 版本

i

忽略无法打印的字符

n

以( 整数) 数字比较

r

倒置排序的顺序

注意 :-k 选项在我们测试的所有系统上都可用,但sort 也认得过时的旧式字段规格。在该定义上,字段与字符位置是从0 开始编号。键值从字段n 中的字符m 开始,定义为:+n.m ,以及键值以-n.m 结束。举例来说,sort+2.1 -3.2 ,等同于sort -k3.2,4.3 。如省略’字符位置,则默认为0 。因此,+4.0nr 与+4nr 表示相同的意义: 一个数值型的键值,从第5 个字段起始处开始,但反向( 由大至小) 排序。

1.1.2 . 字段排序例子

1. 以用户名称排序

[root@local~]#sort -t:-k1,1 /etc/passwd

bin:x:l:1:bin:Ibin:lsbinlnologin

chico :x:12501:1DDD:Chico Marx:Ihvmelahicv:Ibinlbash

daemon:x:2:2:daeman:lsbin:Isbinlnologin

groucho:x:125p3;2ppp:Groucho Marx:lkiome-Igroucho:lbinlsh

gummo:x:12504:3ppp:Gummv Marx:Ihomelgummo:lusrllocallbinlksh93

harpo:x:12502:1ppp:Harpv Marx:lhomelha 印。:Ibinlksh

raot:x:D:O:root:IrvaC:Ibinlbash

zeppo:x:12505:1DDD:Zeppo Marx:Ihamelzeppv:Ibinlzsh

2. 反向uid 的排序

[root@local~]# sort -t:-k3nr /etc/passwd

zappv:x:12505:laa}:2eppo Marx:lhomelzeppo:lhinlzsh

gummo : x:12504:3000:Gummo Marx:Ihvmelgummv:Iusrllvcallbinlksh33

grvuqhv:x:12503:2aaff:Groucho Marx:IhvmelgrvuChv:Ibinlsh

3.passwd 文件里有三个用户拥有共同的GID( 字段4) ,因此我们可以先以GID 排序,再以UID 排序,如下所示:

[root@local~]#sort –t: -k4n –k3n /etc/passwd

root:x:0:0:root:/root:/bin/bash

bin:x:l:l:bin:/bin:/sbin/nologin

daemon:x:2:2:daemon:/sbin:/sbin/nologin

chico :x:12501:1000:Chico Marx:/homelchico:/bin/bash

harpo:x:12502:1000:Harpo Marx:/home/harpo:/bin/ksh

zeppo:x:12505:looo:Zeppo Marx:/home/zeppo:/bin/zsh

groucho:x:12503:2000:Groucho Marx:/home/groucho:/bin/sh

gummo:x:12504:3000:Gummo Marx:/homelgummo:/usr/local/bin/ksh93

4.-u 选项的好用是在于: 它可以要求sort 仅输出唯一的记录,而“唯一的”是指它们的排序键值字段匹配

[root@local~]#sort –t: -k4n -u /etc/passwd

root:x:0:0:root:/root:/bin/bash

bin:x:l:l:bin:/bin:/sbin/nologin

daemon:x:2:2:daemon:/sbin:/sbin/nologin

chico :x:12501:1000:Chico Marx:/home/chico:/bin/bash

groucho:x:12503:2000:Groucho Marx:/home/groucho:/bin/sh

gummo:x:12504:3000:Gummo Marx:/home/gummo:/usr/local/bin/ksh93

1.1.3 . 文本块排序例子

有时,你会需要将多行记录组合而成的数据排序。地址清单就是一个很好的例子,为了

方便阅读,地址记录经常会切断,以一个或数个空行将彼此隔开。

显示地址数据文件

[root@local~]#cat my-friends

SORTKEY: Schlo3 Hans Jurgen

Hans  Jiirgen  Schlof3

Unter den Linden 78

D-10117 Berlin

Germany

 

# SORTKEY: Jones, Adrian

Adrian Jones

371 Montgomexy Park Road

Henley-on-Thames RG9 4AJ

UK

 

#SORTKEY: Brown, Kim

Kim Brown

1841 S Main Street

Westchester , NY 10502

USA

这里的排序小技巧,就是利用awk 处理较一般性的记录分隔字符的能力,识别段落间隔,

在每个地址内暂时使用一个未使用过的字符( 例如使用一个无法打印的控制字符) ,取

代分行,以及用换行字符取代段落间隔.sort 看到的行就会变成这样:

SORTKBY: Schlo3, Hans Jiirgen^ZHans Jiirgen Schlo3^ZUnter den Linden 78^Z...

SORTKEY: Jones, Adrian^ZAdrian Jones^Z371 Montgomery Park Road^Z…

SORTKEY: Brown,Kim^ZKim Brown^Z1841 S Main Street^Z…

在这里,^Z 是一个Ctrl-Z 字符。第一个过滤步骤是通过sort 排序后恢复换行与段落的分隔符号,且排序键值行是容易删除的,如有需要,可使用grep 轻松地删除它们。整个管道看起来就像这样:

    cat my-friends |                    # 在地址数据文件里的管道

   awk -v RS="" ‘{gsub("/n", "^Z");print} ’| # 转换地址为单个行

      sort –f|                     # 排序地址数据,忽略大小写

         awk -v ORS="/n/n" ’{gsub("^Z", "/n");print}’| # 恢复行结构

            grep –v ‘#SORTKEY'       # 删除标记行

函数gsub() 功能为全局性替换(global substitution) ,类似sed 下的s/x/y/g 架构。RS 变量是输入数据的记录分隔器(Record Separator) 。通常输入数据是以换行字符隔开,使每一行成为单个的记录。“RS="" ”是一个特殊用法,指的是记录以空行的方式隔开; 例如每个块或文本段落自成一个记录。这就是我们的例子里输人的数据形式。最后,ORS 指的是输出记录分隔器(Output Record Separator); 以print 显示的每条输出记录会以其值作为终止。一般来说默认值为单个换行字符; 在此设置它为"/n/n" ,是为了保持用空白行分隔记录的输入格式。这个管道应用在上述地址数据文件上的输出为:

Kim Brown

1841 S Main Street

Westchester , NY 10502

LISA

 

Adrian ,Tones

371 Montgomery Park Road

Henley-on-Thames RGR 4AJ

UK

 

Hans  Jiirgen  Schlof3

Unter den Linden 78

D-10117 Berlin

Germany

2. 删除重复

2.1. uniq 命令

2.1.1 . 语法与参数

语法

    uniq[options]

用途

    将输入行按照健值字段与数据类型选项以及 locale 排序。

主要选项

-i 忽略大小写。

-c 计算该行重复的次数。

-d 用于仅显示重复的行。

-u 仅显示未重复的行。

2.1.2 . 例子

[root@local~]#cat Latin-numbers # 显示测试文件

tres

unus

duo

tres

duo

tres

[root@local~]#sort Latin-numbers | uniq # 显示唯一的、排序后的记录

duo

tres

unus

[root@local~]# sort Latin-numbers | uniq –c # 计数唯一的、排序后的记录

2 duo

3 tres

1 unus

[root@local~]# sort Latin-numbers | uniq –d # 仅显示重复的记录

duo

tres

[root@local~]# sort Latin-numbers | |uniq –u # 仅显示未重复的记录

unus

3. 计算行数,字数和字符数

3.1.wc 命令

3.1.1 . 语法与参数

语法

    wc [-lwmc]

用途

    将输入行按照健值字段与数据类型选项以及 locale 排序。

主要选项

-l 仅显示多少行。

-w 仅显示多少字 ( 英文单词 ) 。

-m 多少字符。

-c 字节数。

3.1.2 . 例子

[root@local~]# echo Testing one two three | wc –c # 计算字节数

22

[root@local~]# echo Testing one two three | wc –l # 计算行数

1

[root@local~]# echo Testing one two three | wc –w # 计算字数

4

抱歉!评论已关闭.