Linux下的文本处理工具


文本搜索工具:grep, egrep, fgrep


globbing: 文件名通配

*, ?, [], [^]


p*[0-9]*[^0-9]


既限定了长度,又限定了可用的字符范围


过滤条件:以行为独立单位

The first line.


模式(pattern):以正则表达式的元字符,以及正常字符组合而成


文本处理工具:grep, egrep, sed, awk, vim, nginx


grep: 

Global search REgular expression and Print out the line.


文本搜索工具,根据用户指定的文本模式(正则表达元字符以及正常字符组合而成)对目标文件进行逐行搜索,显示能匹配到的行;


grep命令:

grep [OPTIONS] PATTERN [FILE...]


--color[=WHEN], --colour[=WHEN]

auto

always

never

例子:grep --color=auto "root" /etc/passwd


-o: 只显示被模式匹配到的内容

-i: ignore case,不区分字符大小写

-v: 显示不能够被模式匹配到的行

-E:使用扩展的正则表达式

-A #: 

-B #:

-C # 




正则表达式:REGular EXPression REGEXP

是由元字符及正常字符所书写的模式,其中的元字符不表示字符本身的意义,而是用于表达控制或通配等功能;


基本正则表达式: grep

扩展正则表达式: grep -E, egrep

fgrep: fast, 不支持使用正则表达式


基本正则表达式元字符:

字符匹配:

.  :匹配任意单个字符

[]: 匹配指定范围内的任意单个字符

[^]: 匹配指定范围外的任意单个字符

[0-9], [[:digit:]], [^0-9], [^[:digit:]]

[a-z], [[:lower:]]

[A-Z], [[:upper:]]

[[:space:]]

[[:punct:]]

[0-9a-zA-Z], [[:alnum:]]

[a-zA-Z], [[:alpha:]]

次数匹配:在期望匹配字符后面提供一个控制符,用于表达匹配其前面字符指定的次数

*  : 任意长度,表示0次、1次或多次;

"ab*c"

abbc, ac

abb, 

.*: 任意长度的任意字符

工作于贪婪模式

\?:0次或1次;表示其左侧字符可有可无

"ab\?c"

abbc,

ac, abc

\+: 1次或多次;表示其左侧字符至少出现1次;

"ab\+c"

ac,

abc, abbbbc

\{m\}:m次;表示其左侧字符精确出现m次;

\{m,n\}:至少m次,至多n次;

ab\{2\}c

ac, abc, abbbc

abbc

ab\{0,3\}c

ac, abbbc,

abbbbbc

\{0,n\}:至多n次;

\{m,\}:至少m次;

位置锚定:

^: 锚定行首

^PATTERN

$: 锚定行尾

PATTERN$


^PATTERN$:用模式来匹配整行;

# grep "^[[:space:]]*$" /etc/rc.d/rc.sysinit

^$: 匹配空白行;


单词锚定:由非特殊字符组成的连续的字符串


\< :锚定词首,也可用\b

\<PATTERN, 或\bPATTERN

# grep "\<sh" /etc/passwd


\> :锚定词尾,也可以用\b

PATTERN\>, 或PATTERN\b


\<PATTERN\>:匹配PATTERN能匹配到的整个单词


# ifconfig | grep "\<[0-9]\{2\}\>"


分组:\(\)

注意:分组中的模式,在某次的具体匹配过程中所匹配到的字符,可以被grep记忆(保存于内置的变量中,这些变量是\1, \2, ...),因此,还可以被引用;

\1: 引用,模式中自左而右,由第一个左括号以及与之对应的右括号中的模式所匹配到的内容;

\1: 引用 ,模式中自左右,由第二个左括号以及与之对应的右括号中的模式所匹配到的内容

\(ab\(cd\)mn\) \1 \2


“\(a.b\).*\1"

amb hello anb


He like his lover.

He like his liker.

She love her lover.

She love her liker.


"\(l..e\).*\1"


play.php?a.mp3?search?a.wmv

play.php?where.mp3?hello?when.wmv

\(.*\)\.mp3.*\1\.wvm


练习:

1、显示/proc/meminfo文件中以大写或小写S开头的行;用两种方式;

# grep "^[sS]" /proc/meminfo


2、显示/etc/passwd文件中其默认shell为非/sbin/nologin的用户;

# grep -v "/sbin/nologin$" /etc/passwd | cut -d: -f1


3、显示/etc/passwd文件中其默认shell为/bin/bash的用户;

# grep "/bin/bash$" /etc/passwd | cut -d: -f1


4、找出/etc/passwd文件中的一位数或两位数;

# grep "\<[0-9]\{1,2\}\>" /etc/passwd


5、显示/boot/grub/grub.conf中以至少一个空白字符开头的行;

# grep "^[[:space:]]\+" /boot/grub/grub.conf


6、显示/etc/rc.d/rc.sysinit文件中以#开头,后面跟至少一个空白字符,而后又有至少一个非空白字符的行;

# grep "^#[[:space:]]\+[^[:space:]]\+" /etc/rc.d/rc.sysinit



7、打出netstat -tan命令执行结果中以‘LISTEN’,后或跟空白字符结尾的行;

# netstat -tan | grep "LISTEN[[:space:]]*$"


8、添加用户bash, testbash, basher, nologin (此一个用户的shell为/sbin/nologin),而后找出当前系统上其用户名和默认shell相同的用户的信息;

# grep "^\([[:alnum:]]\+\>\).*\1$" /etc/passwd



扩展的正则表达式:

字符匹配:

.

[]

[^]

次数匹配:

*: 任意次

?:0或1次

+: 至少1次

{m}:精确匹配m次;

{m,n}:至少m次,至多次;

{m,}:至少m次;

{0,n}:至多次;

位置锚定:

^

$

\<, \b

\>, \b

分组:

()


引用:\1, \2, ...

或者:

a|b:a或者b

或者两侧的所有内容;


命令:

grep -E PATTERN FILE...

egrep PATTERN FILE...


练习:

1、显示/proc/meminfo文件中以大写或小写S开头的行;用三种方式;

# grep -E "^[sS]" /proc/meminfo

# grep -E "^(s|S)" /proc/meminfo

# egrep -i "^s" /proc/meminfo


2、显示/etc/passwd文件中其默认shell为非/sbin/nologin的用户;

# egrep -v "/sbin/nologin$" /etc/passwd | cut -d: -f1


3、显示/etc/passwd文件中其默认shell为/bin/bash的用户;

# egrep "/bin/bash$" /etc/passwd | cut -d: -f1


4、找出/etc/passwd文件中的一位数或两位数;

# egrep --color=auto "\<[0-9]{1,2}\>" /etc/passwd


5、显示/boot/grub/grub.conf中以至少一个空白字符开头的行;

# egrep "^[[:space:]]+" /boot/grub/grub.conf


6、显示/etc/rc.d/rc.sysinit文件中以#开头,后面跟至少一个空白字符,而后又有至少一个非空白字符的行;

# egrep "^#[[:space:]]+[^[:space:]]+" /etc/rc.d/rc.sysinit



7、打出netstat -tan命令执行结果中以‘LISTEN’,后或跟空白字符结尾的行;

# netstat -tan | egrep "LISTEN[[:space:]]*$"


8、添加用户bash, testbash, basher, nologin (此一个用户的shell为/sbin/nologin),而后找出当前系统上其用户名和默认shell相同的用户的信息;

# egrep "^([[:alnum:]]+\>).*\1$" /etc/passwd


9、显示当前系统上root、fedora或user1用户的默认shell;

# grep -E "^(root|fedora|user1)\>" /etc/passwd | cut -d: -f7


10、找出/etc/rc.d/init.d/functions文件中某单词后面跟一组小括号的行,形如:hello();

# grep -o -E "\<[[:alnum:]]+\>\(\)" /etc/rc.d/init.d/functions


11、使用echo命令输出一个绝对路径,使用grep取出其基名;

扩展:取出其路径名


# echo /etc/rc.d/init.d/functions | grep -o -E "[[:alnum:]]+/?$" | cut -d/ -f1


12、找出ifconfig命令结果中的1-255之间数字;

# ifconfig | grep -E "\<([1-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\>"



13、挑战题:写一个模式,能匹配合理的IP地址;

1.0.0.1 -- 239.255.255.255


14、挑战题:写一个模式,能匹配出所有的邮件地址;



回顾:

基本正则表达式与grep:

grep [OPTIONS] PATTERN [FILE]...

-v, -o, -i, --color, -E, -A #, -B #, -C #


基本正则表达式:

字符匹配:., [], [^]

次数匹配:*, \+, \?, \{\}

锚定符:^, $, \<, \>

分组和后向引用:\(\), \1, \2, ...


扩展正则表达式与egrep


扩展正则表达式:

字符匹配:., [], [^]

次数匹配:*, +, ?, {}

锚定符:^, $, \<, \>

分组和引用:(), \1, \2, ...

或者: a|b


博客:grep, egrep及相应的正则表达式用法详解

5w1h: what, why, when, who, where, how


文件查找工具:

文件:根据文件的种属性去找到相应文件


文件查找工具:locate, find


locate:根据此前updatedb命令生成的数据库来完成文件查找

查找速度很快

非实时查找,结果不精确;模糊查找;


必要时,可手动执行updatedb命令;


find命令:通过遍历指定的目标目录,实时查找符合指定属性的文件;


精确匹配;速度略慢;


find [OPTIONS] [查找路径] [查找条件] [处理动作]

查找路径:默认为当前路径;

查找条件:默认为指定路径下的所有文件;

处理动作:默认为打印至屏幕;


查找条件:

-name "文件名":文件名支持使用globbing

*, ?, [], [^]


# find /etc -name "passwd*"


-iname "文件名"


-user USERNAME: 根据属主查找

-group USERNAME: 根据属组查找


-uid UID: 根据指定UID查找;

-gid GID: 根据指定GID查找;


-nouser: 查找没有属主的文件;

-nogroup:查找没有属组的文件;


组合查找条件:

与:-a, 查找条件1 -a 查找条件2 -a ...

所有条件必须同时满足

或:-o, 查找条件1 -o 查找条件2 -o ...

满足其中一个条件即可

非:-not, !   

-not 查找条件


# find /tmp -nouser -a -name "*centos*" -ls


# find /tmp -not \( -name "*.txt" -o -name "*.out" \)

# find /tmp -not -name "*.txt" -a -not -name "*.out"


查找条件(2)


-type TYPE: 根据文件类型查找

f: 普通文件

d: 目录文件

l: 符号链接文件

b: 块设备

c: 字符设备文件

p: 命令名管道文件

s: 套接字文件


-size [+|-]#UNIT:

常用单位有:k, M, G


#UNIT: #-1 < x <= #

2k:1.8k, 1.9k, 1.1k

-#UNIT:x <= #-1

-2k: 1k, 0.9k

+#UNIT: x > #

+2k: 2.1k, 3.1k


根据时间戳查找:

以“天”为单位

-atime [+|-]#

#: #= < x < #+1

-#: x < #

+#: x >= #+1


-mtime [+|-]#


-ctime [+|-]#


以“分钟”为单位

-amin [+|-]#

-mmin

-cmin


根据权限查找:

-perm [+|-]MODE

MODE: 与MODE精确匹配

+MODE:任何一类用户的权限只要能包含对其指定的任何一位权限即可;

-MODE:每一类用户的权限都包含对其指定的所有权限;

-222,666,664


练习:

1、查找/var目录下属主为root,且属组为mail的所有文件或目录;

# find /var -user root -a -group mail -ls


2、查找当前系统上没有属主或属组的文件;

进一步:查找当前系统上没有属主或属组,且最近3天内曾被访问过的文件或目录;

# find / \( -nouser -o -nogroup \) -a -atime -3


3、查找/etc目录下所有用户都有写权限的文件;

# find /etc -perm -222 -ls

进一步:查找/etc/目录下所有用户都没有写权限的文件;

# find /etc -not -perm +222


4、查找/etc目录下大于1M,且类型为普通文件的所有文件;

# find /etc -size +1M -a -type f


5、查找/etc/init.d/目录下,所有用户都有执行权限,且其它用户有写权限的文件;

# find /etc/init.d/ -perm -113


6、查找/usr目录下不属于root、bin或hadoop的文件;

# find /usr -not -user root -a -not -user bin -a -not -user hadoop -ls

# find /usr -not \( -user root -o -user bin -o -user hadoop \) -ls


7、查找/etc/目录下至少有一类用户没有写权限的文件;

# find /etc -not -perm -222


8、查找/etc目录下最近一周内其内容被修改过,且不属于root或hadoop的文件;

# find /etc -mtime -7 -a -not \( -user root -o -user hadoop \)