始于linux学习过程中欲检测学习效果,同学推荐了两道正则表达式的题目。这两道题目字数不多,但却引发了我的一段思考。操作环境CentOS6.7 2.6.32-573.22.1.el6.x86_64
现题目整理如下:
【第一则】
请使用正则表达式与sed命令将/etc/passwd内的第一个单词与最后一个单词置换。例如:
sc:x:891:809::/home/sc:/bin/bash#操作之前 bash:x:891:809::/home/sc:/bin/sc#操作之后
【第二则】
请使用正则表达式与sed命令将/etc/passwd内的第一组数字与最后一个单词置换。
sc:x:891:809::/home/sc:/bin/bash#操作之前 sc:x:bash:808::/home/sc:/bin/890#操作之后
解答
首先来看第一则.
首先,我们的主要目标提取第一个单词和最后一个单词,观察单词的特点,纯字母形式,故可以表示为(^[a-zA-Z]*)和([a-zA-Z]*$);
第二步,把剩余的部分看作一个整体,观察特点,我们会发现剩余部分是两个“:”之间的部分,于是可以想到冒号开头、冒号结尾,紧接着,为了完整的表示出这个部分,我们可以使用([^a-zA-Z].*[^a-zA-Z])(如此,三个部分表示完毕);
最后根据sed命令替换的规则,辅以后向引用“\3\2\1”,完成操作!下面贴上命令行:
[root@oldboy~]#sed-r's#(^[a-zA-Z]*)([^a-zA-Z].*[^a-zA-Z])([a-zA-Z]*$)#\3\2\1#g'/etc/passwd bash:x:0:0:root:/root:/bin/root nologin:x:1:1:bin:/bin:/sbin/bin ...... bash:x:889:807::/home/sa:/bin/sa bash:x:890:808::/home/sb:/bin/sb bash:x:891:809::/home/sc:/bin/sc [root@oldboy~]#
小结:我们对文件内容的每一行进行分析,结果发现,按照题目要求可以将一行文字分为,“单词--两个非字母之间的部分--单词”。按照这个模式,我们以单词为用力点,将语句完美分隔开了,shell也没有识别错误。
再来看第二则,这道题目是上一题的升级版本,乍一看可以用是第一题的模式来解题。我们先来整体分析,寻找一下思路。
整体分析:按照题目要求需要调换第一组数字和最后一个单词,由上一题的分析得出,我们可以选择从数字和单词这两点着手实验。我们可以观察出下面这个模式“非数字部分--第一组数字--非字母之间的部分--最后一个单词”。从shell执行解析正则表达式的顺序, 上面这一模式是正确的,能够完整表示出一行的内容。下面贴上命令行:
[root@oldboy~]#sed-r's#(^[^0-9]*)([0-9]*)([^a-zA-Z].*[^a-zA-Z])([a-zA-Z]*$)#\1\4\3\2#g'/etc/passwd root:x:bash:0:root:/root:/bin/0 bin:x:nologin:1:bin:/bin:/sbin/1 ...... sa:x:bash:807::/home/sa:/bin/889 sb:x:bash:808::/home/sb:/bin/890 sc:x:bash:809::/home/sc:/bin/891 [root@oldboy~]#
启发
在学习使用正则表达式的时候,分析要求,选好分隔行信息的关键点,以此完成匹配。