概述
在认识了 char. set 这个概念后, 然后再让我们多认识几个 RE 中常见的 meta 字符:
- 锚点(anchor)
用以标识 RE 于句子中的位置所在. 常见有:
^: 表示句首. 如 ^abc 表示以 abc 开首的句子.
$: 表示句尾. 如 abc$ 表示以 abc 结尾的句子.
<: 表示词首. 如 <abc 表示以 abc 开首的词.
>: 表示词尾. 如 abc> 表示以 abc 结尾的词.
- 修饰字符(modifier)
独立表示时本身不具意义, 专门用以修改前一个 char. set 的出现次数. 常见有:
*: 表示前一个 char. set 的出现次数为 0 或多次. 如 ab*c 表示 a 与 c 之间可有 0 或多
个 b 存在.
?: 表示前一个 char. set 的出现次数为 0 或 1 次. 如 ab?c 表示 a 与 c 之间可有 0 或
1 个 b 存在.
+: 表示前一个 char. set 的出现次数为 1 或多次. 如 ab+c 表示 a 与 c 之间可有 1 或
多个 b 存在.
{n}: 表示前一个 char. set 的出现次数必须为 n 次. 如 ab{3,}c 表示 a 与 c 之间必须
有 3 个 b 存在.{n,}: 表示前一个 char. set 的出现次数至少为 n 次. 如 ab{3,}c 表示
a 与 c 之间至少有 3 个 b 存在.
{n,m}: 表示前一个 char. set 的出现次数为 n 到 m 次. 如 ab{3,5}c 表示 a 与 c 之
间有 3 到 5 个 b 存在.
然而, 当我们在识别 modifier 时, 却很容易忽略"边界(boundary)"字符的重要性.
以刚提到的 ab{3,5}c 为例, 这里的 a 与 c 就是边界字符了.
若没有边界字符的帮忙, 我们很容以作出错误的解读.
比方说: 我们用 ab{3,5} 这个 RE (少了 c 这个边界字符)可以抓到 abbbbbbbbbbc (a 后
有 10 个 b )这串字吗?
从刚才的 modifier 我们一般会认为我们要的 b 是 3 到 5 个, 若超出了此范围, 就不是我
们要表达的.
因此, 我们或会很轻率的认为这个 RE 抓不到结果...
然而答案却是可以的! 为甚么呢?
让我们重新解读 ab{3,5} 这个 RE 看看:
我们要表达的是 a 后接 3 到 5 个 b 即可, 但 3 到 5 个 b 后面我们却没规定是甚么,
因此在 RE 后面可以是任意的文字, 当然包括 b 也可以啦! (明白了吗?)
同样的, 我们用 b{3,5}c 也同样可以抓到 abbbbbbbbbbc 这串字的.
但我们若使用 ab{3,5}c 这样的 RE 时, 由于同时有 a 与 c 这两个边界字符, 那就截然不
同了!
有空再思考一下, 为何我们用下面这些 RE 都可抓到 abc 这串字呢?
x*
ax*, abx*, ax*b
abcx*, abx*c, ax*bc
bx*c, bcx*, x*bc
...(还有更多...)
但, 若我们在这些 RE 前后分别加一个 ^ 与 $ 这样的 anchor, 那又如何呢?
刚学 RE 时, 只要能掌握上面这些基本的 meta 大盖就可以入门了.
一如前述, RE 是一种规范化的文字表达方式, 主要用于某些文字处理工具之间,
如 grep, perl, vi, awk, sed, 等等. 常用以表示一段连续的字符串, 捕获之或替换之.
然而, 每种工具对 RE 表达式的具体解读或有一些细微差异, 不过, 基本原则还是一致的.
只要能掌握 RE 的基本原理, 那就一理通百理明了, 只是在实作时稍加变通即可.
比方以 grep 来说, 在 Linux 上你可找到 grep, egrep, fgrep 这几个程序, 其差异大致如
下:
* grep:
传统的 grep 程序, 在没有参数的情况下, 只输出符合 RE 字符串之句子. 常见参数如下:
-v: 逆反模示, 只输出"不含" RE 字符串之句子.
-r: 递归模式, 可同时处理所有层级子目录里的文件.
-q: 静默模式, 不输出任何结果(stderr 除外. 常用以获取 return value, 符合为 true, 否则
为 false .)
-i: 忽略大小写.
-w: 整词比对, 类似 <word> .
-n: 同时输出行号.
-c: 只输出符合比对的行数.
-l: 只输出符合比对的文件名称.
-o: 只输出符合 RE 的字符串. (gnu 新版独有, 不见得所有版本都支持.)
-E: 切换为 egrep .
* egrep:
为 grep 的扩充版本, 改良了许多传统 grep 不能或不便的操作. 比方说:
- grep 之下不支持 ? 与 + 这两种 modifier, 但 egrep 则可.
- grep 不支持 a|b 或 (abc|xyz) 这类"或一"比对, 但 egrep 则可.
- grep 在处理 {n,m} 时, 需用 { 与 } 处理, 但 egrep 则不需.
诸如此类的... 我个人会建议能用 egrep 就不用 grep 啦... ^_^
* fgrep:
不作 RE 处理, 表达式仅作一般字符串处理, 所有 meta 均失去功能.
好了...
关于 RE 的入门, 我暂时就介绍到这里.
虽然写得有点乱, 且有些观念也不很精确, 不过, 姑且算是对大家有一个交差吧.... ^_^
若这两天还有时间的话, 我再举些范例来分析一下, 以助大家更好的理解.
假如更有可能的话, 也顺道为大家介绍一下 sed 这个工具.
(啊, 这次我不敢作保证了哦... ^_^ )
----------------
(顺道一提: eval )
讲到 command line 的重组特性, 真的需要我们好好的加以理解的.
如此便能抽丝剥襺的一层层的将正个 command line 分析得一清二楚, 而不至于含糊.
假如这个重组特性理解下来来, 那么, 接下来我们介绍一个好玩的命令 --- eval .
我们在不少变量替换的过程中, 常碰到所谓的复式变量的问题, 如:
代码:
a=1
A1=abc
我们都知道 echo $A1 就可得到 abc 这个结果.
然而, 我们能否用 $A$a 来取代 $A1 而同样替换出 abc 呢?
这个问题我们可用很轻松的用 eval 来解决:
代码:
eval echo $A$a
说穿了, eval 只不过是在命令行完成替换重组后, 再来一次替换重组罢了...
转载于:https://blog.51cto.com/qqtthappygo/955798
最后
以上就是纯真冬日为你收集整理的细读shell-6的全部内容,希望文章能够帮你解决细读shell-6所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复